80. 删除有序数组中的重复项 II

80. 删除有序数组中的重复项 II

难度中等477

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

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 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]
解释:函数应返回新长度 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 。 不需要考虑数组中超出新长度后面的元素。

提示:

  • 1 <= nums.length <= 3 * 104
  • 104 <= nums[i] <= 104
  • nums 已按升序排列

思路

恶臭的双指针 - 我的题解

这道题目一看就知道, 是**"双指针"题目**, 然而这个双指针的实现方式可能因人而异.

我一开始的实现思路比较笨拙, 只考虑了这道题本身的情况: 用指针i来记录, 用指针j来遍历. 判断第j和 j +1个元素是否相等,

  1. 若等则将第i和i+1个元素设为第j个元素的值, 然后将i指针移动2位, 并将j移到指向不等于目前元素值的位置上.
  2. 若不等则将第i个元素设为第j个元素的值. 然后i和j同时向后移动.
class Solution {
    public int removeDuplicates(int[] nums) {
        int N = nums.length;
        int i, j;
        i = 0;
        j = 0;
        while (j < N)
        {
            if (j + 1 == N){
                nums[i] = nums[j];
                j++;
                i++;
            }
            else if (nums[j] != nums[j + 1])
            {
                nums[i] = nums[j];
                i ++;
                j ++;
            }
            else
            {
                nums[i] = nums[i + 1] = nums[j];
                while (j < N && nums[j] == nums[i]){
                    j++;
                }
                i += 2;
            }
                        
        }
        return i;
    }
}

很显然, 上面我的双指针实现方法比较啰嗦, 代码也较长. 接下来, 是最为正规, 也最有意义的题解(因为不仅能解决保留2个元素的本题, 而且还能保留任意元素个数) :

正确的双指针 -

设i指针用于记录元素, j指针用于遍历.

对于要保留n个重复元素的数组而言,

  1. 若第i-n个元素和第j个元素的值相等, 那么表示对于这个元素已经保留了足够个数n个, 因此只需将j指针向右移一位即可.
  2. 若不等, 那么表示这个元素距离保留n个数量还不够. 因此将其记录到指针i所对应的空间中, 将i向右移一位. 重复这个过程即可

我都快被自己绕蒙了, 还是留个三叶大佬的题解链接吧 https://www.notion.so/80-II-f3321a2b980a4d6fb07e418c8e083fd2#8e99bf62d33044cf90870a3304f06f2b

以下是我根据上述思路写出的代码

class Solution {
    public int removeDuplicates(int[] nums) {
        int i, j;
        i = j = 2;
        while (j < nums.length)
        {
            if (nums[i - 2] != nums[j])
            {
                nums[i] = nums[j]; 
                i++;
            }
            j++;
        }
        return i;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值