学算法刷LeetCode:01-删除数组中的重复项

543 阅读2分钟

删除数组中的重复项

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

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

解题思路

使用双指针,重写原数组。

步骤

  1. 判断特殊情况
  2. 使用双指针
    1. 初始化两个指针,let p = 0; let q = 1;,遍历数组
    2. 处理两种情况
      1. 如果 nums[q] !== nums[p], 则将 nums[q] 的值复制到 nums[p + 1] 的位置, 并将 q++
      2. 如果 nums[q] === nums[p, 则不需要复制值,直接将 p++
  3. 根据题目要求,返回数组长度 return p + 1。因为p是从0算起的。

代码

JavaScript

var removeDuplicates = function(nums){
  if(nums === null || !nums.length){return 0}
  let p = 0;
  for(let q = 1; q < nums.length; q++){
    if(nums[q] !== nums[p]){
      p++;
      nums[p] = nums[q]
    }
  }
  return p+1
}

Java

public int removeDuplicates(int[] nums){
  if(nums == null || nums.length == 0) return 0;
  int p = 0;
  int q = 1;
  while(q<nums.lenght){
    if(nums[p] !== nums[q]){
      p++;
      nums[p] = nums[q]
    }
    q++;
  }
  return p + 1;
}

复杂度

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

优化思路

考虑如下数组: nums = [1, 2, 3, 4, 5], 每次比较时 nums[p] 都不等于 nums[q],就会将 q 指向的元素原地复制一遍,这个操作没有必要,因此可以添加一个小判断, 当 q - p > 1 时,才进行复制。这里直接使用 qp 比较是因为观察一个连续数字的数组,它们的索引相减值是1,或者使用 nums[q] - nums[p] > 1 也行,结果都一样。不过加了判断之后,需要注意 p 自增的位置,考虑一下,如果先自增后,判断 q - p > 1 的时候,p 的值就和 q 值相等,相减结果为0,也就是 p - q > 1 这个判断下的语句永远也不会执行。那这样就没有起到优化的效果。

写的过程中,一定要注意这些小细节。我也是第二遍重写的时候发现这个问题的。

我相信,跟我一样从头开始刷 LeetCode 的人可能会遇到各种各样的问题,可能在一些成熟的开发者面前这些都不算啥,但是记录下来有助于进步呀!

var removeDuplicates = function(nums){
  let p = 0;
  for(let q = 0; q < nums.length; q++){
    if(nums[q] !== nums[p]){
      // p++
      // nums[p] = nums[q]
      if(q - p > 1){
        nums[p+1] = nums[q]
      }
      p++
    }
  }
  return p + 1;
}