【LeetCode】26.Remove Duplicates from Sorted Array 删除有序链表中的相同元素

一、概述

给一个有序的vector,删除其中的重复元素。要求空间复杂度为O(1),不允许另外新建vector。

我第一反应就是用vector自带的erase函数。但是效果很差。

然后开始思考,我这种方法没有用到有序这一特性,只用到了“相同元素全在一起”这个特性。也就是说,对于如下两个序列:

0111222333445555566

8888885555666111222

我这种算法的效率是一样的。

为了用到有序这一特性,使用赋值操作可以更快。

完美,时间缩短了十倍。

二、分析

1、我的代码一

很简单,从头到尾遍历vector,如果当前元素的值与下一个元素的值相等,则erase当前元素。但要注意erase的应用。

erase函数有两种调用方式:

第一种直接传入一个iterator,那么就将这个iterator对应的元素删除,同时删除这个iterator,返回它的下一个。

第二种则是传入(begin+n),那么就删除第n个元素。

注意,在使用第一种的时候,传入的不能是循环中使用的iterator,否则在erase之后+1时候会报错。你都erase了,变空了,还怎么+1。

在使用第二种的时候,注意每次erase后,vector的长度会变化(这不是废话么)。因此删除后的begin+n其实指向的是删除前的begin+n+1。因此删除后要执行n-1。

代码如下:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0)
            return 0;
        if(nums.size()==1)
        {
            return 1;
        }
        for(int i=0;i<nums.size()-1;i++)
        {
            if(nums[i]==nums[i+1])
            {
                nums.erase(nums.begin()+i);
                i--;
            }
        }
        return nums.size();
    }
};

2、我的代码二

代码二不使用erase,erase太耗费资源了。你想啊,vector就是链表,删除链表中的一个元素多麻烦。不如直接把后面元素放在前面。那么问题来了,我想把后面的元素x放到前面,怎么保证前面没有x呢?

因为vector有序啊。如果x大于前面的最大的元素,那么肯定前面没有x了。

这就是整体思路。

需要维护两个指针。第一个a指向“前面最大的元素”,也就是“最后保留的元素序列中当前的最后一个”。第二个b指向遍历过程中的当前元素。每当b指向的元素大于a,那么就将a后面的元素赋值为b,然后a向后移动一个,b向后移动一个即可。

最后vector前面的n个元素就是从小到大排列的n个不同元素。那如何删除后面的所有元素呢?

resize(n)即可。该函数当n<size()时,截断vector到第n个,n>size()时,在后面填充直到n。

代码如下:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0)
            return 0;
        if(nums.size()==1)
        {
            return 1;
        }
        int now=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[now]<nums[i])
            {
                nums[now+1]=nums[i];
                now=now+1;
            }
        }
        nums.resize(now+1);
        return nums.size();
    }
};

三、总结

当算法的时间复杂度不理想的时候,要考虑以下,我用的算法是否已经用到了题目的所有条件。是不是减少某一个条件算法仍成立?如果仍成立,那么突破点就在这个条件上。类似本题中的有序条件。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值