c++删除数组中重复元素_题解:删除排序数组中的重复项

问题描述:

给定一个排序数组,删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

示例:

给定 nums = [0,0,1,1,1,2,2,3,3,4],函数返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 [0, 1, 2, 3, 4]。可以不考虑数组中超出新长度后面的元素。

思路:

// 最直观的思路是这样的:int len = removeDuplicates(nums);// 在函数里修改输入数组对于调用者是可见的。// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。for (int i = 0; i < len; i++) {    print(nums[i]);}

我们可以使用快慢指针的方法

数组完成排序后,我们可以放置两个指针 i 和 j,其中 i 是慢指针,而 j 是快指针。只要 nums[i] = nums[j],我们就增加 j 以跳过重复项。

当我们遇到 nums[j] !=nums[i] 时,跳过重复项的运行已经结束,因此我们必须把它(nums[j])的值复制到 nums[i + 1]。然后递增 i,接着我们将再次重复相同的过程,直到 j 到达数组的末尾为止。

时间复杂度分析

O(n),假设数组的长度是 n,那么 i 和 j 分别最多遍历 n 步。 

代码实现

int removeDuplicates(vector<int>& nums) { //此处缺少判断0长度的数组    int i = 0; //慢指针指向数组头    for (int j = 1; j < nums.size(); ++j) {        if (nums[i] != nums[j]) { //如果相等,慢指针就不动,快指针移动            nums[++i] = nums[j]; //如果不等,慢指针前进,覆盖            //此处如果先判断++i !=j 再复制,也可以,其实判断也是需要时间的        }    }    return i+1;}

其实,也可以用unique函数,unique函数通常和erase函数一起使用,来达到删除重复元素的目的。

 int removeDuplicates(vector<int>& nums) {    nums.erase(unique(nums.begin(), nums.end()), nums.end());    return nums.size();  }

如果不需要考虑最后的元素,可以直接使用unique。

 int removeDuplicates(vector<int>& nums) {    return unique(nums.begin(), nums.end()) - nums.begin() - 1;   //也可以使用distance(it1, it2)来判断两者之间的距离 }

其实unique函数的内部实现和我们上面的代码是一样的。

iterator My_Unique(iterator first, iterator last){  if (first==last) return last;  iterator result = first;  while (++first != last)  {    if (!(*result == *first))       *(++result)=*first;  }  return ++result;}

需要注意的是,单纯的使用unique函数的话,容器的长度并没有发生变化,只是元素的位置发生了变化。unique函数通常和erase函数一起使用,来达到删除重复元素的目的。

iterator unique(iterator it_1,iterator it_2,bool MyFunc);

unique函数可以自定义一个判重自定义函数,类似sort函数里面的。

bool cmp(int a, int b){    return a > b;}

有什么问题,可以给留言或者扫码加微信群讨论。

bff80d56f28dcf987e28a7d1d6a84fc1.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值