题目:
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,2], Your function should return length =2
, with the first two elements ofnums
being1
and2
respectively. It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,0,1,1,1,2,2,3,3,4], Your function should return length =5
, with the first five elements ofnums
being modified to0
,1
,2
,3
, and4
respectively. It doesn't matter what values are set beyond the returned length.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.
Internally you can think of this:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeDuplicates(nums);
// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
print(nums[i]);
}
这个题目描述得实在是太复杂了,简而言之就是要把一个有序的数组中的所有重复元素删掉,更准确地说,是把数组中所有不重复的元素都放在数组的前n位(假设有n个不重复的元素),并且不能使用额外的空间,只能修改函数的输入,最后需要返回不重复的元素个数(就是n)。
思路:
设置两个指针,一个快指针和一个慢指针,都从头开始跑。如果快慢两个指针指向的元素大小相同,那么快指针就往前走一步,直到两个指针指向的元素大小不同时暂停,说明快指针就指向了下一个不重复的元素,那么此时修改慢指针的下一个元素为当前快指针的元素,就相当于把下一个不重复的数字放到了当前数字后面,慢指针再指向这个刚被修改的元素,继续重复上述的步骤跑下去,直到快指针遍历完整个数组,这时候返回慢指针的index+1就是最终的结果了(因为index是从0开始的而我们要返回元素个数)。
代码如下,时间复杂度O(n),运行时间24ms:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0) return 0;
int i = 0;
for (int j = 1; j < nums.size(); j++) {
if (nums[i] != nums[j]) {
nums[i + 1] = nums[j];
i += 1;
}
}
return i + 1;
}
};
2022.10.22
重新回到这道题,已经忘了是用快慢指针了。知道是用快慢指针以后就写出来了,虽然还是写了一小会儿。今天的思路是让fast从1走,slow从0走;如果fast == slow那就要remove,就要让fast++;如果fast != slow就说明要保留fast这个元素,但是由于slow是从0开始的,它是要保留的,所以slow得先++以后再让新的slow = fast,再fast++。slow相当于是指向当前数组需要保留长度的index,所以最后需要返回的是数组的长度,于是最后return slow + 1。写完交完准备来写总结的时候才发现这样写出的代码可以再简化,就是以下option 2的写法,但是感觉option 1还是逻辑上更直观一些?
class Solution {
public int removeDuplicates(int[] nums) {
int len = nums.length;
if (len == 0) {
return len;
}
int fast = 1;
int slow = 0;
while (fast < len) {
// option 1
if (nums[fast] == nums[slow]) {
fast++;
} else {
slow++;
nums[slow] = nums[fast];
fast++;
}
// option 2: improvement
/*
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
fast++;
*/
}
return slow + 1;
}
}