説明
昇順の配列番号が与えられた場合、各要素が最大2回表示されるように、その場で繰り返される要素を削除し、削除された配列の新しい長さを返す必要があります。
余分な配列スペースを使用しないでください。入力配列をその場で変更し、O(1)の余分なスペースを追加する必要があります。
説明:
戻り値が整数なのに、出力の答えが配列であるのはなぜですか?
入力配列は「参照」によって渡されることに注意してください。これは、関数内の入力配列の変更が呼び出し元に表示されることを意味します。
内部操作は次のように想像できます。
// numsは「参照」によって渡されます。つまり、実際のパラメーターのコピーを作成しないでください
int len = removeDuplicates(nums);
//関数の入力配列の変更は、呼び出し元に表示されます。
//関数によって返される長さに応じて、その長さ内の配列内のすべての要素が出力されます。
for(int i = 0; i <len; i ++){ print(nums [i]); }
例1:
入力:
nums = [1,1,1,2,2,3 ]出力:5、nums = [1,1,2,2,3]
説明:関数は新しい長さの長さ= 5を返し、前部を返す必要があります元の配列の5つの要素が1、1、2、2、3に変更されました。新しい長さを超える配列内の要素を考慮する必要はありません。
例2:
入力:nums = [0,0,1,1,1,1,2,3,3]
出力:7、nums = [0,0,1,1,2,3,3]
説明:関数は新しい長さ= 7で、元の配列の最初の5つの要素が0、0、1、1、2、3、3に変更されます。新しい長さを超える配列内の要素を考慮する必要はありません。
促す:
0 <= nums.length <= 3 * 104
-104 <= NUMS [I] <= 104
NUMS昇順に
ソース:LeetCode
リンク:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/
解決する
class Solution {
public:
// 第一版,暴力解法,直接遍历元素发现多余2个的直接调用vector接口erase删除
// 这个办法非常不好,每次删除会导致删除点后面的所有元素都前移拷贝
int removeDuplicates_1e(vector<int> &nums) {
const int n = 2; // 最多保留2个重复元素
int current = nums[0];
int i = 0;
int curNum = 0;
while (i < nums.size()) {
if (nums[i] == current) {
++curNum;
++i;
continue;
}
// 出现新元素
current = nums[i];
if (curNum > n) {
int extraTwoNum = curNum - n; // 超出2的重复数量
nums.erase(nums.begin() + i - extraTwoNum, nums.begin() + i); // 删除元素
i -= extraTwoNum; // 删除extraTwoNum个元素后,i下标需要前移extraTwoNum位置
}
curNum = 1;
++i;
}
// 处理如[...., x, x, x, x]的场景
if (curNum > n) {
int extraTwoNum = curNum - n; // 超出2的重复数量
nums.erase(nums.begin() + i - extraTwoNum, nums.begin() + i); // 删除元素
}
return nums.size();
}
// 第二版,使用辅助空间,空间复杂度O(N),不符合题意
int removeDuplicates_2e(vector<int> &nums) {
const int n = nums.size();
if (nums.size() < 3) {
return n;
}
vector<int> rec;
rec.reserve(n);
int cnt = 1;
int cur = nums[0];
rec.push_back(nums[0]);
for (int i = 1; i < n; ++i) {
if (nums[i] == cur) {
if (cnt < 2) {
rec.push_back(nums[i]);
++cnt;
}
} else {
rec.push_back(nums[i]);
cur = nums[i];
cnt = 1;
}
}
nums.assign(rec.cbegin(), rec.cend());
return rec.size();
}
// 第三版,双指针,原地处理,空间复杂度O(1)
int removeDuplicates(vector<int> &nums) {
const int n = nums.size();
if (nums.size() < 3) {
return n;
}
int k = 0; // [0...k]保留满足条件的元素
int cnt = 1; // 初始情况下已经有一个元素了
for (int i = 1; i < n; ++i) {
if (nums[i] == nums[k]) {
if (cnt < 2) {
nums[++k] = nums[i];
++cnt;
}
} else {
nums[++k] = nums[i];
cnt = 1;
}
}
return k + 1;
}
};