什么是二分查找
举个例子,现在有一个数组arr=[1,2,6, 8,10,12,18],我们想要查找6在数组中的位置返回6的索引。通常来说,我们使用一个for循环就可以做出来。
<script>
let arr=[1,2,6,8,10,12,18]
function search(arr,index){
for(let i=0;i<arr.length;i++){
if(arr[i]==index){
return i
}
}
return -1
}
let aa=search(arr,6)
alert(aa)//输出值为2
</script>
for循环做较少的数据是很简单,那么做上万甚至上亿条数据呢,使用for循环一位一位判断,它是非常耗费内存的。
那么使用二分查找,就是我们会有三个指针,一个指向第一个元素,一个指向最后一个元素,还有一个指向我们的中间值,所以二分查找也叫作折半查找。
二分查找的算法
<script>
let arr = [1, 2, 6, 8, 10, 12, 18]
function search(arr, target) {
// 定义指向开始的指针
let start = 0;
// 定义指向最后一个元素的指针
let end = arr.length - 1;
// 保证开始的指针必须要比结束指针小
while (start <= end) {
// 定义中间值得指针
let mid = (parseInt(start + end) / 2)
// 如果中间值恰好等于target,直接返回中间值的下标
if (arr[mid] == target) {
return mid
// 中间值大于目标值,说明目标值必定在开始指针和中间值的区间
} else if (arr[mid] > target) {
// 将结束指针移动到中间值前一位
end = mid - 1
// 中间值小于目标值,目标值必定在中间值到结束指针的区间
} else {
start = mid + 1
}
}
return -1
}
let aa = search(arr, 6)
// 输出值为2
alert(aa)
</script>
虽然说看代码量来说二分查找比我们的传统方法多,但是对于性能来说,二分查找要高很多。
注意:使用二分查找,数组必须要是排序好的。
二分查找的实例
以力扣的374题猜数字为例:
猜数字游戏的规则如下:
每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
-1:我选出的数字比你猜的数字小 pick < num
1:我选出的数字比你猜的数字大 pick > num
0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/guess-number-higher-or-lower
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
* Forward declaration of guess API.
* @param {number} num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* var guess = function(num) {}
*/
/**
* @param {number} n
* @return {number}
*/
var guessNumber = function(n) {
let start=1;
let end=n;
while(start<=end){
let mid=parseInt((start+end)/2)
if(guess(mid)==0){
return mid
}else if(guess(mid)==-1){
end=mid-1
}else{
start=mid+1
}
}
};