【No.4】【LeetCode系列】【数组】80.删除排序数组中的重复项 II|刷题打卡

236 阅读3分钟

1. 题目描述

题目地址

题目描述

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素最多出现2次,返回移除后数组的新长度。

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

示例

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

方法:双指针

思路

  • 主旨:主旨很简单,只要定义这是一个最多只有两个元素重复的已排序数组,然后遍历这个数组,不断维护这个定义就可以了。类似题目可参考下列题目,都使用了几乎完全相同的思路。
  • 操作流程:定义一对指针p1和p2,初始状态p1指向数组第二个元素(当前元素),p2指向p1后边一个元素(长度小于等于2的数组可以直接返回,无需计算)。然后p2开始依次向后移动,同时比较p2和p1,判断是否需要用p2覆盖p1后边的元素,达到删除重复项的目的。此时以p1和p2位一个判断组合,分两种情况:
    1. p2和p1所指向的元素相等。此时需要比较p2和p1之前的元素,p2和p1的前一个元素相等,那么说明p2指向的元素是需要被删掉的,此时让p2指向下一个元素,其他什么都不做。直到碰到一个与p1的前一个元素不相等的元素。此时p1和p1前一个元素已经重复了两遍,那么就将p2所指向的元素,赋值给p1的后一个元素,覆盖最开始的那个多余的重复值。
    2. p2和p1所指向的元素不相等。这说明此时不存在超过两次重复的元素,使p1指向下一个元素即可。

代码实现

public int removeDuplicates(int[] nums) {
        if (nums.length <= 2) {
            return nums.length;
        }
        int i = 1, j = i + 1;
        while (j < nums.length) {
            if(nums[i] != nums[j] || (nums[i] == nums[j] && nums[j] != nums[i - 1])){
                nums[++i] = nums[j];
            }
            j++;
        }
        return i + 1;
    }

复杂度分析

  • 时间复杂度:O(n)。总共有n个元素,p1和p2最多遍历2n步。
  • 空间复杂度:O(1)。只需要常数的空间存放若干变量。 执行结果 本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情