二分查找的实现、特性及实战题目解析

109 阅读1分钟

二分查找

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

所以,想要进行二分查找,需要数据有以下前提:

  1. 目标函数单调性(单调递增或者递减)
  2. 存在上下界(bounded)
  3. 能够通过索引访问(index accessible)

代码模板

function binarySearch(arr, target) {
  var left = 0;
  var right = arr.length - 1;

  while(left <= right) {
    mid = Math.floor((left + right) / 2); // 可能不能整除哦

    // 找到啦
    if (arr[mid] == target) return mid;
      else if (arr[mid] < target) (left = mid + 1);
        else (right = mid - 1);
  }
}

示例

比如 在递增数组 [10, 14, 19, 26, 27, 31, 33, 42, 44]中,查找 31 所在的下标 先查找中间值27, 发现 31 比27大,左边界变成 31 所在下标,右边界仍是数组结尾,这时会对比中间值 35 与 31 大小,接着移动边界,直到找出 31

实战题目

leetcode-cn.com/problems/sq…

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

分析题目

因为 x = y²,这个抛物线是在第一象限的,所以 y 的值是单调递增的,且有边界,因为 x 是非负整数,所以 y 最小值为0 (当x为0时), y最大值就为 x,所以针对 y 的求值可以用二分查找。

coding

var mySqrt = function(x) {
  if (x == 0 || x == 1) return x;

  var left = 1, right = x;
  var mid;

  while(left <= right) {
    // 防止越界
    mid = left + Math.floor((right - left) / 2);

    if (mid * mid > x) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }

  return right;
};