这道题目,我一开始以为要改变nums里面的元素,所以使用了vector的erase方法,所以运行时间较长,56ms。第一个版本,每次只erase一个元素,第二个版本,每次erase一段重复的元素。第一个版本的代码如下:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0)
return 0;
int len = (int)nums.size(), i, last = nums[0], del = 0; // del记录已经删除了多少重复元素
for (i=1; i<len-del; i++) { // i的范围随着del的增加而变小
if (nums[i] != last) {
last = nums[i];
} else {
nums.erase(nums.begin()+i); // 删除第i个元素
del++;
i--; // 删除当前元素后,需要改变i的数值
}
}
return len-del;
}
第二个版本的代码如下:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0) {
return 0;
}
// del记录已经删除了多少重复元素,start记录要删除的一段元素的起始点
int len = (int)nums.size(), i, last = nums[0], del = 0, start = 0;
for (i=1; i<len-del; i++) {
if (nums[i] != last) {
last = nums[i];
if (i-start >= 2) {
nums.erase(nums.begin()+start, nums.begin()+i-1);
del += i-start-1;
i -= i-start-1; // 删除一段元素之后,需要改变i的数值
}
start = i;
}
}
if (start != len-del-1) { // 如果nums的最后一个元素重复了
nums.erase(nums.begin()+start, nums.begin()+len-del-1);
del += len-del-1-start;
}
return len-del;
}
考虑到第一个版本和第二个版本使用到了vector的erase方法,nums出于动态的变化之中,导致代码逻辑不够清晰,调试起来也比较困难。因此我又参考了网上的一些解法。第三个版本的算法思想如下:
1. i从1开始,遇见和上一个不一样的,就把nums[i]放到j指向的位置,j++
2. nums[i]==nums[i-1],则i继续往下走
代码如下:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0) {
return 0;
}
int j = 1, len = (int)nums.size(); // j指向的位置,就是新元素应该放入的位置
for (int i=1; i<len; i++) {
if (nums[i] != nums[i-1]) {
nums[j] = nums[i];
j++;
}
}
return j;
}