26. 删除排序数组中的重复项
题目
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
思路
这题要求是直接改变它的vector而不是新建一个,所以我们可以开一个map来记录一下哪些元素出现过,如果出现过的话就用erase函数消掉。需要注意的是用erase的时候不能直接用,要用it=nums.erase(it);而且it不能++ 因为在删除一个元素的时候,其参数为指向相应元素的迭代器,而在删除一段元素的时候,参数为指向一段元素的开头的迭代器以及指向结尾元素的下一个元素的迭代器。
代码
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
map<int,int>mp;
vector<int>::iterator it;
int len = nums.size();
for(it = nums.begin();it != nums.end();)
if(!mp[*it])
{
mp[*it]=1;
it++;
}
else
it=nums.erase(it);
return nums.size();
}
};
vector的erase用法
错误示范:
vector<int>vec;
vector<int>::iterator it;
for(it = vec.begin();it!=vec.end();it++)
if(!mp[*it])
{
mp[*it]=1;
}
else
nums.erase(it);
这样的话else语句里面的it已经指向了被删除的数的下一个迭代器,如果此时再进行it++的话,迭代器就不知道指向哪里了。
正确写法
vector<int>vec;
vector<int>::iterator it;
for(it = nums.begin();it != nums.end();)
if(!mp[*it])
{
mp[*it]=1;
it++;
}
else
nums.erase(it);
在不操作的时候it++ 操作的时候直接erase it就指向了被删数的下一个迭代器。
vector用unique去重
如果题目没有要求有序输出的话,可以考虑unique去重。unique把没有重复的元素都放到vector的前面,覆盖了之前的数,有几个不重复的就会覆盖几个,剩下没有覆盖的还在vector的相应位置。
unique的覆盖
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>vec;
vec.push_back(0);
vec.push_back(0);
vec.push_back(0);
vec.push_back(1);
vec.push_back(1);
vec.push_back(1);
vec.push_back(2);
vec.push_back(2);
vec.push_back(2);
vec.push_back(3);
vec.push_back(3);
vec.push_back(4);
sort(vec.begin(),vec.end());
vector<int>::iterator it;
for(it = vec.begin();it!=vec.end();it++)
cout<<*it<<" ";
cout<<endl;
it = unique(vec.begin(),vec.end());
// vec.erase(it,vec.end());
for(it = vec.begin();it!=vec.end();it++)
cout<<*it<<" ";
}
输出:
0 0 0 1 1 1 2 2 2 3 3 4
0 1 2 3 4 1 2 2 2 3 3 4
可见0 0 0 1 1 被 0 1 2 3 4 覆盖了
使用方法
由于unique只能判别相邻重复的元素,所以需要对vector先进行排序,这样就可以让重复的元素都挨在一起,从而在后面用unique的时候可以把重复的元素都忽略。
然后迭代器赋值给unique(vec.begin(),vec.end()) 即第一个没有被没有重复元素覆盖的地方的迭代器,这时候用erase方法把当前位置到end的vector元素都删掉就可以了。
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>vec;
vec.push_back(0);
vec.push_back(0);
vec.push_back(0);
vec.push_back(1);
vec.push_back(1);
vec.push_back(1);
vec.push_back(2);
vec.push_back(2);
vec.push_back(2);
vec.push_back(3);
vec.push_back(3);
vec.push_back(4);
sort(vec.begin(),vec.end());
vector<int>::iterator it;
for(it = vec.begin();it!=vec.end();it++)
cout<<*it<<" ";
cout<<endl;
it = unique(vec.begin(),vec.end());
vec.erase(it,vec.end());
for(it = vec.begin();it!=vec.end();it++)
cout<<*it<<" ";
}
输出:
0 0 0 1 1 1 2 2 2 3 3 4
0 1 2 3 4