力扣第八十题-删除有序数组中的重复项 II

243 阅读3分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

前言

力扣第八十题 删除有序数组中的重复项 II 如下所示:

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

示例 1:

输入: nums = [1,1,1,2,2,3]
输出: 5, nums = [1,1,2,2,3]
解释: 函数应返回新长度 length = 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]
解释: 函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。

一、思路

这一题是要将有序数组中超过两个的元素都删除掉,且必须原地修改

这很自然的就可以想到使用滑动窗口来解决这类计数问题。

我们滑动窗口的左边界指向连续元素的左边,右边界指向连续元素的右边。 这样当某个窗口中的元素个数大于 2 时,就将之后的所有元素都向前移动即可。

大致的步骤如下所示:

  1. 从左至右遍历数组
  2. nums[i] == nums[left] 时,让窗口的右边界 right++
  3. nums[i] != nums[left] 时,且窗口中元素大于 2 个, right -left > 2,则计算出移动的距离 move += right-left-2
  4. 在遍历的过程中,只要 move > 0,就将该元素前移,nums[right-move] = nums[right]
  5. 遍历结束后,如果最后一个窗口中的元素是否大于 2,则更新移动距离 move += right-left-2(因为最后一个连续窗口的大小可能大于 2
  6. 返回新数组长度 len - move 作为结果

举个例子

此处以 nums = {0,0,1,1,1,1,2,2} 作为例子

初始值:left = right = 0move = 0

  1. 开始遍历数组 nums
  2. right = 2 时,出现了nums[2] != nums[0],但此时窗口中元素不大于 2。故只需将 left = right
  3. right = 6 时,出现了nums[6] != nums[2],此时窗口中元素大于 2,计算出移动距离 move = 2,再将 left = right
  4. move > 0,后续的遍历都需要将元素前移
  5. 最终数组更新为 {0,0,1,1,2,2,2,2},返回新的长度 len - move = 8 -2 =6 即可

二、实现

实现代码

实现代码与思路保持一致

    public int removeDuplicates(int[] nums) {
        int len = nums.length;
        if (len < 3){   // 特殊情况
            return len;
        }
        int left = 0;
        int right = 0;
        int move = 0;
        while (right < len) {
            if (nums[left] != nums[right]) {
                // 判断当前窗口长度是否超过2
                if (right - left > 2){
                    move += right-left-2;
                }
                left = right;
            }
            // 元素前移
            if (move > 0) {
                nums[right-move] = nums[right];
            }
            right++;
        }
        // 可能会出现最后的字符未处理的情况
        if (right - left > 2) {
            move += right-left-2;
        }
        return len - move;
    }

测试代码

public static void main(String[] args) {
    int[] nums = {0,0,1,1,1,1,2,2};
    new Number80().removeDuplicates(nums);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~