代码随想录day1|Leecode 704. 二分查找,27. 移除元素

72 阅读2分钟

704. 二分查找

 /**
   * @param {number[]} nums
   * @param {number} target
   * @return {number}
   */
    var search = function (nums, target) {
      let middle, left = 0;
      let right = nums.length - 1;
      while (left <= right) {
        middle = Math.floor((left + right) / 2);
        if (nums[middle] === target) {
          return middle;
        } else if (nums[middle] > target) {
          right = middle - 1;
        } else left = middle + 1;
      }
      return -1;
    };

通过定义左右指针 left 和 right ,计算中间指针 middle 来逐步缩小查找范围。

如果中间元素 nums[middle] 等于目标值 target ,则返回中间索引。

如果中间元素大于目标值,将右指针更新为 middle - 1 。

如果中间元素小于目标值,将左指针更新为 middle + 1 。

如果在整个查找过程中都未找到目标值,返回 -1 。

Tips: 定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)

区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

27. 移除元素(双指针)

/**
    * @param {number[]} nums
    * @param {number} val
    * @return {number}
    */
    var removeElement = function (nums, val) {
      let slow = 0;
      for (let fast = 0, len = nums.length; fast < len; fast++) {
        if (nums[fast] !== val) {
          nums[slow++] = nums[fast];
        }
      }
      return slow;
    };

  • 初始化指针:在函数内部,首先初始化了两个指针 slow 和 fast,分别表示慢指针和快指针。slow 指针初始化为 0fast 指针也初始化为 0。同时,获取数组的长度 len
  • 遍历数组:使用 for 循环,fast 指针从数组的第一个元素开始遍历,直到最后一个元素。
  • 条件判断:在循环内部,使用 if 语句判断当前 fast 指针所指向的元素是否不等于 val
  • 移除元素:如果当前元素不等于 val,则将其赋值给 nums[slow],并且 slow 指针向前移动一步。这实际上是将不等于 val 的元素复制到数组的左边。
  • 忽略目标值:如果当前元素等于 val,则 fast 指针继续向前移动,而 slow 指针保持不变,这样等于 val 的元素就会被跳过,不会被复制到数组的左边。
  • 返回结果:循环结束后,nums 数组中所有不等于 val 的元素都被复制到了数组的左边,slow 指针指向的是最后一个不等于 val 的元素的下一个位置。返回 slow,即移除了目标值 val 后的元素数量。

总的来说,这个算法使用了两个指针来遍历数组,一个指针用于复制元素,另一个指针用于跳过不需要的元素。这种算法的时间复杂度为 O(n),空间复杂度为 O(1),其中 n 是数组的长度。