力扣 80. 删除有序数组中的重复项 II 同向快慢双指针
给你一个有序数组 nums
,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按升序排列
题解
在原表基础上修改,用两个同向指针,一慢一快 slow=0 fast=1
,向右遍历原表,cnt=0
记录重复次数,
同时slow
是新表(在原表上修改得到)的长度下标,slow
到哪里则新表更新到了哪里;
- 对比
slow
和fast
位置的元素,如果相等,即nums[slow]==nums[fast]
,说明是同一个元素(题目允许最多保留两个相同元素),记为A,用cnt++
记录出现次数,接下来判断处理:- 如果
cnt==1
,A刚好出现了两次,题目需要保留A两次,先将slow++
,新表的长度加一,接下来给此位置赋值,nums[slow]=nums[fast];
;注意A记录了两次,因为slow++
前可以省略num[slow]=A
,因为num[slow]本来就=A
,不需要写这一句 - 如果
cnt!=1
,则A出现了不止两次,因为之前出现两次我们已经保留过了,此时我们不需要再保留A,那我们就不用处理了 fast++
,不管A出现几次,fast
都要右移
- 如果
nums[slow]!=nums[fast]
,将两个元素记为A,B,因为A是已经处理过的元素,而B是新出现的,所以我们将B添加到新表中,先将slow
增加一,再把B赋值给这个位置,最后将fast
右移,写成一句:nums[++slow]=nums[fast++]
;再重置cnt
查看代码
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow=0,fast=1;
int cnt=0;
while(fast<nums.size()){
if(nums[slow]==nums[fast]){
cnt++;
if(cnt==1){//slow 和 fast 指向一样,说明此元素出现两次
slow++;
nums[slow]=nums[fast];//
}
//大于两次不予处理
//移动
fast++;
}
else {
nums[++slow]=nums[fast++];
cnt=0;
}
}
return slow+1;
}
};