题目
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]
接着移除有序数组里面的重复数字那道题目,如果允许重复两次的情况下,应该怎么处理呢?
例如给你一个有序的数组A = [1, 1, 1, 2, 2, 3],你的函数需要返回长度=5,而且A= [1, 1, 2, 2, 3]
分析
和之前那个题目有点类似哈,只是说允许连续的两次重复,可以有3种解法:
1. 我们增加一个duplicate的计数器,如果计数器达到给定的值,那么就不在继续填充我们新的数组,否则就继续填充。如果遇到新的值,就更新计数器为0。
优势:容易扩展到允许n次重复的情况
劣势:需要额外维护一个计数器,增加了代码的复杂度,出错几率比较大
2. 可以判断当前值和新数组的上一个值及上上一个值是否相等,如果相等久忽略,否则加入。
优势:逻辑比较简单,只需要判断要遍历的值和新数组的上一个值及上上一个值是否相等就可以,清晰切不容易出错。
劣势:比较难以扩展到允许n次重复的情况
3. 基于方案2的改进策略:由于数据是有序的,如果允许n次重复,那么我们这个时候只需要判断当前值是否与新数组的n-1个值是否相等就可以了。
优势:逻辑简单清晰,不容易出错
劣势:比较难以考虑到,需要分析数据的情况(可以把数据列出来,举几个例子总结出来)
代码
代码只实现方案1和方案3,方案2大家可以自行实现。
/****************************************
* 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]
****************************************/
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
/* Time: O(n), Space: O(1) */
int removeDuplicates1(vector<int> &nums) {
if (nums.empty()) {
return 0;
}
int start = 0;
int duplicate = 1;
for (int i = 1; i < nums.size(); i++) {
if (nums[start] != nums[i] || duplicate < 2) {
if (nums[start] != nums[i]) {
duplicate = 0;
}
start++;
nums[start] = nums[i];
}
duplicate++;
}
for (int i = nums.size() - 1; i > start; i--) {
nums.pop_back();
}
return start + 1;
}
/* Time: O(n), Space: O(1) */
int removeDuplicates2(vector<int> &nums) {
if (nums.empty()) {
return 0;
}
int start = 1;
int duplicate = 2;
for (int i = 2; i < nums.size(); i++) {
if (nums[start - 1] != nums[i]) {
start++;
nums[start] = nums[i];
}
}
for (int i = nums.size() - 1; i > start; i--) {
nums.pop_back();
}
return start + 1;
}
};
int main(void) {
Solution* s = new Solution();
vector<int> nums;
nums.push_back(1);
nums.push_back(1);
nums.push_back(1);
nums.push_back(2);
nums.push_back(2);
nums.push_back(2);
nums.push_back(3);
nums.push_back(3);
nums.push_back(4);
cout << "Solution 1: " << s->removeDuplicates1(nums) << endl;
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << ",";
}
cout << endl;
cout << "Solution 2: " << s->removeDuplicates2(nums) << endl;
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << ",";
}
delete s;
return 0;
}