LeetCode 26 详解
题目
给你一个升序排列 的数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致 。 由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有k个元素,nums的前k个元素应该保存最终结果。将最终结果插入nums的前k个位置后返回k 。 不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
思路分析
(1)当我第一次看到这个题目的时候,我脑子里面的第一想法就是双层for
循环+if
判断(去重) ,事实证明还是有那么一点点肌肉记忆的
(2)我的想法是定义变量i
和j
,用于表示两个不同的元素,但是写到后面我发现,如果我是用两个变量去计算的话,我无法表达出去重的效果,后来就手足无措了,不知道怎么解决
代码实现
int removeDuplicates(int* nums, int numsSize){ int i, j; for(i = 1, j = 0; i < numsSize; i++) { if(nums[i] == nums[j]) { continue; } nums[++j] = nums[i]; } return ++j; } 复制代码
代码详解
(1)代码的第一行并没有出乎我的意料之外(看来跟我想的一样),但是值得注意的是:它这里定义的i
和j
是用于表示快慢指针,这一题本质上是用指针来进行比较的
(2)使用for
循环遍历数组,这一题比较好的地方在于它把i
和j
放在了同一个for
循环里面,从而避免了双层for
循环给读者带来的困扰
(3)使用if
进行判断,如果数组nums
里面的i
和j
相等的话,就跳转到赋值操作
重点解析:这里之所以进行赋值操作是因为代码中存在快慢指针,这两个指针存在的意义即为:快指针大步走,慢指针慢慢走并匹配元素
。这里可以理解为一快一慢同时遍历一个数组,一旦遇到相同的就交换数值并把快指针前进一位,读者亦可以把慢指针看作一个搬运的角色,不断的往前进直到匹配完全部的元素
(4)由于题目要求返回具体数组的长度,所以根据上述操作我们返回慢指针j
的长度就可以了,至于为什么要先自增,我只能说:慢指针移动一次才算一次结果,你觉得呢?