方法:双指针
题目要求:对给定的有序数组 numsnums 删除重复元素,在删除重复元素之后,每个元素只出现一次,并返回新的长度,上述操作必须通过原地修改数组的方法。
由于给定的数组是有序的,所以数组的元素是按照从小到大排序,因此对于任意的,如果有
,那么对于任意的 ,一定有
通俗的讲,对于两个相同元素之间的元素,一定也相同。
题目要求更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。所以可以考虑用双指针的方法来做。
双指针的意思就是定义两个指针,分别指向数组的某个元素,比如两个元素分别为慢指针和快指针,那么,快指针就负责遍历整个数组的各个元素,而慢指针用来与快指针进行比较,来进一步的更新原数组,使得数组最终满足题目要求。
在数组长度小于2的时候,也就是1或0时,数组无需改动,直接返回数组长度即可。当数组大于1时,第一个元素实际上也无需变动,所以只需要从下标为1的元素开始即可。所以可以定义两个指针的初始值都为1,然后快指针遍历数组元素,遍历到与上一个元素不一样时,交给慢指针,更新原数组,然后慢指针向后一位,重复操作,直至遍历完整个数组为止。
这里可以举个例子:例如如下数组 {0,0,1,1,1,2,2,3,3},完整的过程如下:
首先定义两个指针初始值为1。
快指针开始遍历数组,指向2的位置,判断前后的元素,发现0不等于1,则把该值赋给慢指针。即如下图:
然后慢指针会指向下一个元素,如图所示:
接下来重复操作,直到快指针指向5的时候,也就是元素2,判断与上一个元素不同,则把2这个值赋给慢指针,如下图所示:
接下来,直到快指针遍历到元素3的时候,会把这个值赋给慢指针,如图所示:
最终,数组就完成遍历以及更新,如图所示:
整体的思路就是这样,C++代码实现如下:
class Solution
{
public:
int removeDuplicates(vector<int>& nums)
{
if (nums.size() < 2)
{
return nums.size();
}
else
{
int fast = 1, slow = 1;
while (fast < nums.size())
{
if (nums[fast] != nums[fast - 1])
{
nums[slow] = nums[fast];
++slow;
}
++fast;
}
return slow;
}
}
};
复杂度分析
时间复杂度:O(n),其中n是数组的长度。快指针和慢指针最多各移动n次
空间复杂度:O(1)。只需要使用常数的额外空间。