【c++】LeetCode80. 删除排序数组中的重复项II(0ms)

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;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值