【Leetcode】26,27删除数组重复项

题目

题目26

  • 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
  • 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例:

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

题目27

  • 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
  • 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
  • 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

刚开始看完题目,不知道应该怎样去解决,为什么不创建新数组就可以“原地”删除元素,在参看力扣优秀解法之后,其实只要返回的新长度的范围内符合即可。

双指针法

题26解法

首先题目是已经排序后的数组,在不考虑数组中超出新长度后面的元素的前提下,可以分别定义快慢指针(i是慢指针,j是快指针),如果重复(nums[i]==nums[j]的情况),直接跳过,将重复的一一向前覆盖(nums[++i] = nums[j];),最终返回新长度即可。

/**
 * 删除数组中重复的项,并返回数组的长度
 * @param nums 传入已排序的数组
 * @return 返回无重复项数组的长度
 */
public int removeDuplicates(int[] nums) {
    if (nums.length == 0) return 0;
    //定义慢指针
    int i = 0;
    //定义快指针
    for (int j = 1; j < nums.length; j++) {
        //相等情况直接跳过
        //不相等时,将nums[j]的值赋值给nums[i+1],然后递增i
        if (nums[j] != nums[i]) {

            nums[++i] = nums[j];
        }
    }
    //返回无重复项数组的新长度
    return i + 1;
}

题27解法一

类似地,也可以运用双指针法求解。还是定义快慢两个指针,只要快指针索引值和目标值不相等,即nums[j]!=val,就可以将该索引值赋值给前面的慢指针索引值,即nums[i]=nums[j],两个指针同时递增,直到快指针截至,最终的新长度就是慢指针i的值。

 /**
 * 删除所有重复的val值,并返回数组的长度
 * @param nums 传入的数组
 * @param val  删除数组中的所有val
 * @return 返回无重复数组的长度
 */
public int removeDuplicates(int[] nums, int val) {

    int i = 0;
    for (int j = 0; j < nums.length; j++) {
        if (nums[j] != val) {
            nums[i++] = nums[j];
        }
    }
    return i;
}

复杂度分析

  • 时间复杂度:O(n) 假设数组总共有n个元素,i和j分别最多遍历n步
  • 空间复杂度:O(1)

题27解法二

题27的解法一很暴力,但是在遇到特殊情况时其实进行了多余的步骤:假如数组包含需要删除的数很少的时候,nums=[4,1,2,3,5],val=4时,题目中特意提示可以不用考虑新数组的元素顺序,可以在遇到nums[i]==val时,将当前元素和最后一个元素交换,并释放数组的最后一个元素。

如果被交换的最后一个元素正好也是想要删除的值,他会在下一次迭代时被发现。

public int removeDuplicates00(int[] nums, int val) {
    int i = 0;
    //定义变量len操作数组长度,因为本身是final的
    int len = nums.length;
    while (i < len) {

        if (nums[i] == val) {
            //相等的情况,将第一个与最后一个交换,
            // 因为数组顺序可以更改,[4,1,2,3,5],val=4,
            //可以避免不必要的移位
            nums[i] = nums[len - 1];
            len--;
        } else {
            i++;
        }
    }
    return len;
}

复杂度分析

  • 时间复杂度:O(n),i和n最多遍历n步,且赋值操作的次数等于将要删除元素的数量,如果要移除的元素很少,效率会很高。
  • 空间复杂度:O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值