0.题目描述
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
1.解法一
首先考虑平凡的情况,输入数组为空数组或只有一个元素时,输出原数组,返回值为原数组长度。
因为数组是有序数组,所以我们从前往后遍历,若前后两个数字相同则继续遍历,若前后两个数字不同,则删除前者。注意当两个元素相同时,这时候删除当前元素后,应该进行i--操作,若无这个操作,那么不能操作3个连续元素,比如,0,0,0,1,1删除后则为0,0,1
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0||nums.size()==1)
{
return nums.size();
}
else
{
int num = 0;
int length = nums.size();
for (int i = 0; i < nums.size()-1; i++)
{
if (nums[i] == nums[i + 1])
{
std::vector<int>::iterator it = nums.begin() + i;
nums.erase(it);
num++;
i--;
}
}
return length-num;
}
}
};
本题解法时间复杂度为O(n)
提交结果:
2.解法二:双指针
上面解法是遍历每一个元素,一旦相等则删除当前元素。考虑到是有序数组,所以解法二可以将所有相等元素先保持不动,当遍历到不相等元素时,再把前面这几个相等的元素取一个元素出来。代码如下:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0||nums.size()==1)
{
return nums.size();
}
else
{
int length=nums.size();
int i = 1;
for (int j = 0; j < nums.size() - 1; j++)
{
if (nums[j] != nums[j + 1])
{
nums[i] = nums[j+1];
i++;
}
}
return i;
}
}
};
值得一提的是,这种方法,数组的后半部分如何我们不用管,只需要管通过nums[i]赋值过的数组的前半部分,然后输出前半部分的数值,提交。所以数组长度其实并没有变,只是我们return了前面部分数组的长度值,系统任务前面部分的数组就是我们最好所求的删除过指定值的数组。
虽然平均时间复杂度与上面的解法一样,但是很多情况下这种解法会更快。
提交结果: