二分查找
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
所以,想要进行二分查找,需要数据有以下前提:
- 目标函数单调性(单调递增或者递减)
- 存在上下界(bounded)
- 能够通过索引访问(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
实战题目
实现 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;
};