https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/
LeetCode80. 删除排序数组中的重复项II
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,1,2,3,3],
函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。
你不需要考虑数组中超出新长度后面的元素。
和第26题很相似,唯一的区别就是多了个个限制条件:每个元素最多出现两次。
(26题题解https://blog.csdn.net/BackingEgg/article/details/106938916)
法一(用erase函数):
我们可以设一个计数器count来存储相同元素出现的次数。若两元素相同,count++;若不同,count = 0。当 count = 1 的时候,若再出现重复项,这说明该元素已经出现 3 次了,可以用 erase() 把重复元素删除。
【erase()可删除指定位置的元素,里面的参数为迭代器。】
时间复杂度:O(nm)。n是数组的长度,m 是 erase() 的时间复杂度,当然m是会变的。
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int count = 0; // 计算重复出现的次数,注意这里的count是从0开始计数的
for(int i = 1; i < nums.size(); i++)
if(nums[i] == nums[i-1] ) {
if(count >= 1){ // 出现次数大于2次,在这里的count=1 说明重复项会有3个
nums.erase( nums.begin() + i ); //没想到吧,erase还能这样用
i--;
count ++;
} else { //发现第一个重复项,注意此时该元素出现两次了。
count ++;
}
} else { // 后面的不是重复元素,把计数清空
count = 0;
}
return nums.size();
}
};
法二(双指针、快慢指针):
法一中,erase浪费了大量没必要的时间。因为每次erase时,都要移动后面的所有元素来填补前面的被移除所留下的空位,这太费时间了吧。
不如直接把后面符合要求的元素覆盖到前面的重复项。
例如: [1,1,1,2,3,3],我只要把后面的233向前移一个位置把重复的那个 1 覆盖了,变成 [1,1,2,3,3,3],接着只要取前面的 5 个元素即可。
大致思路:设置两个指针,l 、r 分别为0、1,和一个计数器count。慢指针表示符合要求的元素组中最后一个元素;快指针用于判断该元素是否符合要求(重复),当然要与count一起才好判断。
只要遍历一遍数组便可。( leetcode 用时 0ms ,emmmmmmmmm)
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0) return 0;
// 代码一
int l = 0;
int count = 0;
for(int r = 1; r < nums.size(); r++) {
if( nums[r] != nums[l] ){
l++;
count = 0;
} else {
count ++;
if(count == 1) {
l++;
}
}
nums[l] = nums[r];
}
return l+1;
// 代码二,与 代码一 的部分细节不同,但基本思路还是一样的。
int l = 0;
int count = 0;
for(int r = 1; r < nums.size(); r++) {
if(nums[l] == nums[r]) {
count++;
if(count == 1) {
l++;
nums[l] = nums[l-1]; //因为 count = 0 和 count = 1 时,这两个数是要一样的。这一步很关键。
}
} else {
count = 0;
nums[++l] = nums[r];
}
}
return l+1;
}
};