力扣(删除有序数组中的重复项I/II)
在 LeetCode 的数组类题目中,有序数组去重是经典且高频的题型 。今天我们聚焦 删除有序数组中的重复项(题号 26) 和 删除有序数组中的重复项 II(题号 80) ,用双指针技巧优雅解决,带你理清解题思路,掌握这类题的通用解法。
一、题目回顾与分析
(一)删除有序数组中的重复项(简单)
题目要求:给一个非严格递增的数组nums
,原地删除重复元素,让每个元素仅出现一次,保持相对顺序,返回新长度k
,且需保证nums
前k
个元素是唯一元素并按初始顺序排列。
(二)删除有序数组中的重复项 II(中等)
题目要求:同样原地操作,不过允许元素最多出现两次,超过两次的重复元素需删除,返回处理后数组新长度。
这两道题核心都是 “原地修改” ,要控制额外空间复杂度为
O(1)
,双指针是绝佳选择 —— 用指针标记有效元素位置,遍历数组处理重复情况。
二、双指针解法逻辑拆解
(一)题目 26:每个元素仅出现一次
class Solution {public int removeDuplicates(int[] nums) {// 特殊情况处理:数组为空直接返回0if (nums.length == 0) return 0; // 双指针,key指向“待填充唯一元素”的位置,初始在第一个元素int key = 0; // len遍历数组,从第二个元素开始对比for (int len = 1; len < nums.length; len++) { // 发现当前元素与key位置元素不同,说明是新的唯一元素if (nums[key] != nums[len]) { key++; // key移动到下一个待填充位置nums[key] = nums[len]; // 将不同元素放到key位置}}// key从0开始,所以有效长度是key + 1return key + 1; }
}
逻辑详解:
- 指针分工:
key
是 “慢指针”,标记当前已处理好的唯一元素的最后位置;len
是 “快指针”,负责遍历数组找新元素。 - 核心判断:当
nums[len] != nums[key]
,说明遇到新的唯一元素,把len
位置元素挪到key + 1
位置(key
先自增再赋值 ),保证nums
前key + 1
个元素是去重后的结果。比如数组[1,1,2]
,初始key=0
,len=1
时元素相同不处理;len=2
时nums[2]=2 != nums[0]=1
,key
变为 1,nums[1]=2
,最终数组前2
个元素[1,2]
,返回2
。
(二)题目 80:元素最多出现两次
class Solution {public int removeDuplicates(int[] nums) {// 数组长度小于3时,本身就满足“最多出现两次”,直接返回原长度if (nums.length <= 2) return nums.length; // key初始指向第三个位置(索引2),因为前两个元素不管是否重复都可保留int key = 2; // len从第三个元素开始遍历(索引2)for (int len = 2; len < nums.length; len++) { // 对比当前元素与“往前数第二个有效位置”的元素if (nums[key - 2] != nums[len]) { // 不同则说明可作为新的有效元素,放到key位置nums[key] = nums[len]; key++; // key后移,标记下一个待填充位置}}return key; }
}
逻辑详解:
- 指针逻辑升级:因为允许最多两次重复,所以判断条件变为
nums[key - 2] != nums[len]
。key - 2
位置能反映 “前面已经保留的元素情况”—— 若当前遍历元素和key - 2
位置元素不同,说明加入后不会超过两次重复(比如数组[1,1,1,2,2,3]
,key
初始为 2,len=2
时nums[0] == nums[2]
,不处理;len=3
时nums[1] != nums[3]
(nums[1]=1
,nums[3]=2
),把2
放到key=2
位置,key
变为 3 ,以此类推,最终前key
个元素满足最多两次重复的要求。 - 边界处理:数组长度小于等于 2 时,本身无需处理,直接返回原长度,简化逻辑。
三、两道题的共性与差异总结
(一)共性
- 双指针模式:都用两个指针,一个(
key
)标记有效元素的边界,一个(len
)遍历数组找新元素,通过对比决定是否 “接纳” 当前元素到有效区域。 - 原地修改:不依赖额外数组存储结果,直接在原数组上覆盖、调整,契合题目空间复杂度要求。
(二)差异
- 重复次数限制:题目 26 限制 “最多 1 次”,所以对比条件是和
key
位置元素是否相同;题目 80 允许 “最多 2 次”,对比条件变为和key - 2
位置元素是否相同,通过调整对比的 “参考位置”,灵活控制重复次数。 - 指针初始值与返回值:题目 26 需考虑数组为空情况,
key
从 0 开始,返回key + 1
;题目 80 数组长度小于 3 时直接返回原长度,key
初始从 2 开始,返回key
即可,反映出不同重复次数限制下,有效区域的初始化和结果计算的细微区别。