leetCode -- 删除有序数组中的重复项

leetCode – 删除有序数组中的重复项

题目描述

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array

题目说明

  1. 根据题目要求,不能使用额外数组
  2. 那么可以想到使用双指针法进行遍历
  3. 当然为了让解法更具有一般性,我们将原问题的「最多保留 1 位」修改为「最多保留 k 位」
  4. 由于是保留 k 个相同数字,对于前 k 个数字,我们可以直接保留。
  5. 对于后面的任意数字,能够保留的前提是:与当前写入的位置前面的第 k 个元素进行比较,不相同则保留。

测试用例

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [1,,2,,3,4]
输出:4, nums = [1,2,3,4]
解释:函数应该返回新的长度 4 , 并且原数组 nums 的前四个元素被修改为 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。```

解题方法

一.双指针

解题思路
  1. 因为不能利用额外的数组空间,那么可以考虑用两个指针遍历
  2. 比较 p 和 q 位置的元素是否相等。
  3. 如果相等,q 后移 1 位
  4. 如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
    重复上述过程,直到 q 等于数组长度。
  5. 返回 p + 1,即为新数组长度。
解题代码

源代码:

class Solution {
    public int removeDuplicates(int[] nums) {
        //先判断是否为空或长度为1
        if(nums == null ||nums.length == 1){
            return nums.length;
        }
        //创建两个指针
        int p = 0,q = 1;
        //当还没有循环完所有的数字时
        while(q < nums.length){
            //如果后面的数字和前面的一样,就将后面的指针后移一位
            if(nums[p] == nums[q]){
                q ++;
            }else{
                //如果后面的比前面的大则前面指针往前移一位
               // 并将后面的值赋值给前面,然后后指针后移一位
                p ++;
                nums[p] = nums[q];
                q ++;
            }
        }
        //返回的是前指针加一
        return p+1;
    }
}

简化一下:

class Solution {
    public int removeDuplicates(int[] nums) {
       int n = nums.length;
       int j = 0;
       for(int i = 1;i < n;i ++){
           if(nums[i] != nums[j]){
               nums[++j] = nums[i];
           }
       }
       return j + 1;
    }
}
测试结果

源代码:
在这里插入图片描述

简化后:
在这里插入图片描述

二. 通用解法

详细可看:【宫水三叶】一题双解

作者:AC_OIer
链接:详细解释

解题思路

举个例子,我们令 k=1,假设有样例:[3,3,3,3,4,4,4,5,5,5]

  1. 设定变量 idx,指向待插入位置。idx 初始值为 0,目标数组为 []

  2. 首先我们先让第 1 位直接保留(性质 1)。idx 变为 1,目标数组为 [3]

  3. 继续往后遍历,能够保留的前提是与 idx 的前面 1 位元素不同(性质 2),因此我们会跳过剩余的 3,将第一个 4 追加进去。idx 变为 2,目标数组为 [3,4]

  4. 继续这个过程,跳过剩余的 4,将第一个 5 追加进去。idx 变为 3,目标数组为 [3,4,5]

  5. 当整个数组被扫描完,最终我们得到了目标数组 [3,4,5] 和 答案 idx 为 3。

解题代码
class Solution {
    public int removeDuplicates(int[] nums) {
        int index = 0,k = 1;
        for(int x : nums){
            //每次取出一个数,然后跟前面的数判断,如果相同则保留,不同则舍弃
            //比如输入[1,2,3,4]
            //开始的时候,0<1,故nums[0] = 1;index = 1;
            //nums[1-1] != 2,故nums[1] = 2;index = 2;
            //nums[2-1] != 3,故nums[2] = 3;index = 3;
             //nums[3-1] != 4,故nums[3] = 4;index = 4;
             //返回4
            if(index < k || nums[index - k] != x ) nums[index++] = x;
        }
        return index;
    }
}
测试结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值