题目:
Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?
For example,
Given sorted array A = [1,1,1,2,2,3]
,
Your function should return length = 5
, and A is now [1,1,2,2,3]
.
代码:
class Solution { public: int removeDuplicates(int A[], int n) { if (n <= 2) return n; int index = 2; for (int i=2 ; i<n; i++) { if ( A[index-2]!=A[i] ) { A[index++] = A[i]; } } return index; } };
Tips:
1. index始终指向下一个要插入元素的位置
2. 判断当前元素与index-2位置元素是否相等,如果不等就可以插入,保证没有连续三个相同的元素
3. 这里用到些数学归纳法的技巧:
a. 只要保证第1-第3个元素不是都相同的
b. 并且再后面每一步添加元素的时候判断都不是相同的
则可得结论一直到条件结束,调整后的数组中不会有三个连续重复的元素
========================================
第二次过这道题卡住了一下,复习了第一次写的程式,改出了AC的代码。
class Solution { public: int removeDuplicates(vector<int>& nums) { if ( nums.size()<3 ) return nums.size(); int prev = 2; for ( int i=2; i<nums.size(); ++i ) { if ( nums[prev-2]!=nums[i] ) { nums[prev++] = nums[i]; } } return prev; } };
tips:
这种数学归纳法之类的去重代码,可以总结出一定的规律
第一个指针 prev = 可以保持的重复数量 (这个指针指示当前可插入的位置)
第二个指针 i 从 可以保持重复数量下标开始 一直到数组长度最后
去重条件判断nums[prev-可以保持重复的数量]!=nums[i]
这样就可以获得满足题意的程式。
================================
这里还有一种特殊的case,如果出现重复的就不要了呢?写出了下面的程式
// special case class SolutionS{ public: static int removeDuplicates(vector<int>& nums) { if ( nums.size()<2 ) return nums.size(); int i=1; int prev = nums[0]!=nums[1] ? 1 : 0; while (i<nums.size()-1) { if (nums[i]!=nums[i-1] && nums[i]!=nums[i+1]) { nums[prev++]=nums[i]; } i++; } if ( nums[i]!=nums[i-1] ) nums[prev++]=nums[i]; return prev; } };
这个程式是自己写的,自测了一些case。
思路很朴素:
1. 维护一个prev作为待插入的位置
2. 判断一个元素与前后元素是否相等
3. 处理第一个和末尾元素(第一个没有前驱,末尾没有后继,所以要特殊处理)
====================================================
还有一种情况,如果数组不是排序的,就用hashtable记录每个数字出现的次数。