您好,欢迎来到筏尚旅游网。
搜索
您的当前位置:首页JS二分查找

JS二分查找

来源:筏尚旅游网

🐒题目

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

🐔思路

这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素。有两种方法实现,时间都是复杂度:O(log n) 空间复杂度:O(1)

实现思路:

  1. 定义两个指针,左指针(left)指向数组第一个元素,右指针(right)指向数组最后一个元素
  2. 取数组中间(nums[mid])的值和目标值(target)比较
  3. 如果中值小于目标值,说明目标值在后半数组,将左指针(left)指向[mid+1];若中值大于目标值,说明目标值在前半数组,将右指针(right)指向[mid-1]。如果相等就直接返回
  4. 如果左指针指向的值的索引大于右指针指向的值的索引,说明已经查找完了也没找到目标值,返回-1

🐸方法一

第一种写法,我们定义了一个搜索区间为左闭右闭区间 [left, right] 。这个定义非常重要,因为它决定了我们如何更新搜索的边界。

有如下两点:

  • while (left <= right) 要使用 <= ,当 left = right 时,搜索区间仍然包含了一个元素,这个元素有可能是我们要找的目标值。因此,在 left 等于 right 的情况下继续搜索是有意义的。
  • if (arr[mid] > target) right 要赋值为 mid - 1,说明目标值在前半数组,那么接下来要查找的右区间结束下标位置就是 mid - 1。
  • if (arr[mid] < target) right 要赋值为 mid + 1,说明目标值在后半数组,那么接下来要查找的右区间结束下标位置就是 mid + 1。

      // 二分查找
      function binarySearch(arr, target) {
        // 将数组的第一个和最后一个元素赋值给left和right
        let left = 0;
        let right = arr.length - 1;
        while (left <= right) {
          const mid = Math.floor((left + right) / 2);
          if (arr[mid] === target) {
            return mid;
          } else if (arr[mid] < target) {
            left = mid + 1;
          } else {
            right = mid - 1;
          }
        }
        return -1;
      }
      const arr = [1, 3, 5, 7, 9, 11, 13];
      console.log(binarySearch(arr, 7));

🦖方法二

如果说定义 target 是在一个在左闭右开的区间里,也就是 [left, right) ,那么二分法的边界处理方式则截然不同。

有如下两点:

  • while (left < right),这里使用 < ,当 left 等于 right 时,区间内实际上没有任何元素,因为右边界是开区间,不包含 right
  • if (nums[middle] > target) right 更新为 middle,由于我们的搜索区间是左闭右开的,即 [left, right),我们需要将搜索范围缩小到左半部分,并且排除掉已经检查过的 nums[middle]
/**
 * 在有序数组中查找目标值,如果找到则返回目标值的索引,否则返回-1
 *
 * @param arr 有序数组
 * @param target 需要查找的目标值
 * @returns 目标值的索引,如果未找到则返回-1
 */
function binarySearch(arr, target) {
  // 将数组的第一个和最后一个元素赋值给left和right
  let left = 0;
  let right = arr.length - 1;
  while (left < right) {
    const mid = Math.floor((left + right) / 2);
    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid;
    } else {
      right = mid;
    }
  }
  return -1;
}
const arr = [1, 3, 5, 7, 9, 11, 13];
console.log(binarySearch(arr, 7));

🐳总结

二分法的核心在于通过不断地将搜索区间一分为二,来逐步缩小搜索范围,直至找到目标值或确定目标值不存在。而在这个过程中,搜索区间的定义(是左闭右闭、左闭右开,还是其他)以及相应的边界处理方式是至关重要的。

📖参考笔记:

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- efsc.cn 版权所有 赣ICP备2024042792号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务