【LeetCode】80. Remove Duplicates from Sorted Array II解法及注释

80. Remove Duplicates from Sorted Array II

Total Accepted: 71844 Total Submissions: 220521 Difficulty: Medium

Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?

For example,
Given sorted array nums = [1,1,1,2,2,3],

Your function should return length = 5, with the first five elements of nums being 1122 and 3. It doesn't matter what you leave beyond the new length.

【分析】

     此题的关键在于不利用额外空间而完成数字的删除,因此,我们只能在现有空间,也就是输入数据所在的空间对数据进行操作。根据题意,我们需要将去除重复后的数据依次排在原数组的前面,因此,不可免要对数据进行移动操作,关于移动数据,一般有两种方案:1、整体移动,当遍历到题目所指的重复数据后,我们将其后面的数据整体移动一位,从而将重复数据覆盖,如此,最糟糕的情况,输入的数组n个数据全相同,我们需要移动[(n-3)+(n-4)+...+0],当n比较大时,时间复杂度为O(n2);2、“双指针”,一个指针负责遍历数组,一个指针始终指向下一个无重复数据的存放位置,逐次移动,时间复杂度为O(n).

【解法及注释】

     根据分析,我将两种方法的程序均进行了测试,效率相差不多,这可能与测试案例的数据规模比较有关。

方法一:

class Solution33 {
public:
    int removeDuplicates(vector<int>& nums) {
        
        if(nums.size()<3)return nums.size();
        int result=1;//记录删除重复后的数据长度
        int count=0;//标记重复
        int move=0;//移动次数
        
        for(int i=0;i<nums.size()-1;)
        {
            if(nums[i]>nums[i+1])//原数组是排序的,每次遇到重复,就将其移动到数组的末尾,其后的数据则前移1位
            {                    //因此,数组尾部的数据会比原数组尾部的数据小,这个特点可以作为判断遍历完成的条件
               break;
            }
            else if(nums[i]!=nums[i+1])//相邻元素不等
            {
                result++;
                count=0;
                i++;//控制循环
                move=0;
            }
            else if(nums[i]==nums[i+1])//相邻数据相等
            {
                if(count==2)//已经重复(超过2)
                {
                    count=2;
                    move++;//记录移动次数
                    int temp=nums[i+1];//把重复数据移动到数组尾部
                    for(int k=i+1;k<nums.size()-1;k++)//整体前移
                    {
                        nums[k]=nums[k+1];
                    }
                    nums[nums.size()-1]=temp;//交换到尾部
                    if(move>nums.size()-i-2)//避免陷入死循环
                    i++;
                }
                else //该数据两次出现
                {
                    count=2;//标记
                    result++;//记录
                    i++;//进入下一次循环
                    move=0;
                }
            }
        }
        return result;
        
    }
};
方法二:

class Solution {
public:
    int removeDuplicates(vector<int> &nums) 
    {
        if(nums.size() < 3) return nums.size();
        int length = 1;
        int flag = 1;//标记重复(超过2次)
        
        for(int i = 1; i < nums.size(); i++)
        {
            if(nums[i] != nums[i-1])//相邻数据不等,将数据存储到length指向的空间
            {
                nums[length++] = nums[i];
                flag = 1;//标记
            }
            else if(flag == 1)//出现相等数据,且与之前的数据不等
            {
                nums[length++] = nums[i];//将数据存储到length指向的空间
                flag++;//标记改变
            }
            else//出现相等数据,且之前已经出现了2个,因此i指向的数据不是期望的数据,不保存
                continue;
        }
        return length;
    }
};




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jin_Kwok

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值