Description:
Follow up for “Remove Duplicates”:
What if duplicates are allowed at most twice?
由于follow up Problem 26,因此还是要求in-place。
Example:
Given sorted array nums = [1,1,1,2,2,3],
仍旧是排好序的数组
Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. It doesn’t matter what you leave beyond the new length.
同样,有效长度之后的元素是什么不重要。
Language: C++
解法一:
思路:大体思路与26相同,关键地方在于这里允许最多重复一次,也就是有两个相同元素是允许的。那么就要考虑怎么知道这一次重复的元素是第几个重复的呢?比26稍微复杂的地方在于当判断当前元素与它前面一个元素相等时,如何知道它是第几个重复的呢?很自然的想到用flag变量来控制。flag表示当前元素是第几个重复的。
如果当前元素和它前面一个元素不同时,说明是新的元素(sorted array的特性),此时重置flag为0;如果当前元素和它前一个元素相同时,flag加1,判断当前flag是否等于1,如果是,则说明这个元素是允许的,也就是只重复了一次,否则(因为必定不为0),即大于等于2时,说明这个元素是要被删掉的,也就是当前k位置上的元素是要被replace的,k不动,res减1,直到下一次遍历到一个新的元素,再把那个元素赋给当前k位置。
基本思想:同26,两个指针
Time: O(n)O(n)
Space: O(1)O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==1)
return 1;
int k = 1;//保证[0...k)范围里的都没有重复元素
int res = nums.size();
int flag = 0;//如果为0或1则在允许的条件中,否则就是需要删除的多余元素
for(int i = 1; i < nums.size(); i++){
if(nums[i]!=nums[i-1]){
flag = 0;//对于新的元素,flag重置为0
if(k != i)
nums[k++] = nums[i];
else
k++;
}
else{//当前元素与它前面元素重复
flag++;
if (flag==1){
if(k!=i)//avoid unnecessay copy
nums[k++] = nums[i];//重要!!!!
else
k++;//说明此时是第二个相同的元素,符合条件此时也是符合条件的,k可以加一
}
else
res--;
}
}
return res;
}
};
算法细节:
特别需要注意的是,当第一次提交结果出错的原因是,没有考虑到当当前元素与它之前元素重复且它是第一次重复的情况下,也要赋值nums[k] = nums[i], 如下:
Input: [1,1,1,1,3,3]
Expected: [1,1,3,3]
Output: [1,1,3,1]
错误原因就在于当i遍历到第二个3时,k在索引位置3(也就是input的第4个1的位置),当前nums[i]还是符合条件的,所以要把nums[i]赋给nums[k];之所以没考虑到这个问题是因为只想到k=i的时候,这个赋值是unnecessary的,所以为了避免unnecessary copy,可以判断一下k和i是否相等,然后再赋值。
由此可见Medium的题其实是在Easy的基础上多加一两个条件而已,找到思路以后,其实并不难。
这是在Leetcode上独立做出来的第一道Medium的题!纪念一下哈哈!
Happy Coding!
6117



被折叠的 条评论
为什么被折叠?



