返回

用 JavaScript 化腐朽为神奇:巧妙删除有序数组中的重复项

前端

引言

在编写算法时,我们经常会遇到处理数组的场景。其中一个常见问题就是删除数组中的重复项。对于无序数组,我们可以使用各种方法,例如哈希表或排序加遍历。然而,对于有序数组,我们可以采用一种更巧妙的方法,它不仅简洁高效,而且可以在原地修改输入数组,而无需使用额外的空间。

算法详解

我们提供的 JavaScript 代码巧妙地利用了有序数组的特性。它使用两个指针,一个指针指向当前元素,另一个指针指向下一个不重复的元素。算法步骤如下:

  1. 初始化两个指针:i 指向数组的开头,j 指向数组的下一个不重复元素。
  2. 遍历数组,如果 nums[i]nums[j] 相等,则跳过 nums[i] 并继续前进。
  3. 如果 nums[i]nums[j] 不相等,则将 nums[j] 的值赋给 nums[i],然后将 j 向前移动一位。
  4. 重复步骤 2 和 3,直到遍历完整个数组。
  5. 返回 j,它表示删除重复项后的数组新长度。

代码实现

/**
 * 原地删除有序数组中的重复项
 * @param {number[]} nums 有序数组
 * @return {number} 删除重复项后的数组新长度
 */
const removeDuplicates = (nums) => {
  if (!nums || nums.length === 0) {
    return 0;
  }
  let i = 0;
  let j = 1;
  while (j < nums.length) {
    if (nums[i] === nums[j]) {
      j++;
    } else {
      i++;
      nums[i] = nums[j];
      j++;
    }
  }
  return i + 1;
};

复杂度分析

  • 时间复杂度:O(n),其中 n 为数组的长度。算法遍历数组一次,因此时间复杂度为 O(n)。
  • 空间复杂度:O(1)。算法在原地修改输入数组,不需要额外的空间,因此空间复杂度为 O(1)。

示例

const nums = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7];
const newLength = removeDuplicates(nums);
console.log(`删除重复项后的数组:${nums}`);
console.log(`新长度:${newLength}`); // 输出:8

结论

我们巧妙地利用了有序数组的特性,设计了一种简洁高效的算法来删除重复项。该算法在不使用额外数组空间的情况下,原 地 修改输入数组,并且时间复杂度仅为 O(n)。掌握这种算法,将大大提升你的 JavaScript 编码能力,助你写出更出色的代码!