一、题目
- 80. 删除有序数组中的重复项 II - 力扣(LeetCode)
- 给你一个有序数组
nums
,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。- 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
二、思路
- 由于允许元素出现2次,所以不能和上一个元素比较,而是应该和上上个元素比较,举个栗子:
1 1 1 2 2 3 3 4 若是只允许元素出现一次,
^ ^ <= 那这里 fast 指针是与 nums[slow - 1] 进行比较
slow fast (校验的是元素的前 1 个位置)
1 1 1 2 2 3 3 4 但是允许元素出现两次,
^ ^ <= 这里的 fast 指针是与 nums[slow - 2] 进行比较
slow fast (校验的是元素的前 2 个位置)
- 归纳一下,如果允许保留 k 次,那就应该与 nums[slow - k] 进行比较,具备一定的推广性,由此得到解法一;
三、解法
解法一
class Solution {
public int removeDuplicates(int[] nums) {
return handle(nums, 2);
}
public int handle(int[] nums, int k) {
int len = nums.length;
if (len <= k) {
return len;
}
int slow = k;
for (int fast = k; fast < len; fast++) {
if (nums[fast] > nums[slow - k]) {
nums[slow++] = nums[fast];
}
}
return slow;
}
}
解析:还是用老朋友快慢指针:慢指针标定当前最后一个应保留元素,而快指针负责遍历整个数组,一旦快指针发现标定的值大于慢指针 k 位之前的数,说明已经慢指针已经保留了足够的(k位)元素,慢指针向后移动一位继续下一轮的比较*此时 [慢指针后,快指针前] 已不存在小于慢指针的数*,因为所有这些数均已被填充为慢指针所指的这个元素(这里建议画个草稿理解一下);