前言
算法是一组完成任务的的指令。
(大概就是,你今天要上班,但是你还要买杯咖啡。算法:出门->星巴克->公司)
二分查找
二分查找其实是我们生活中经常用到的逻辑。
比如你的小姐妹买了件200元以内的衣服,让你猜价格。我们不会从1元开始往上猜,为了猜的次数最少,我们会从中间的数字100开始猜。
我:“100元”
姐妹:“没那么贵”
我:“(此时100元-200元的数字都能排除,再取中间值50)50元”
姐妹:“没那么便宜”
我:“(取50-100之间的数字)75”
姐妹:“对了”
嗯,恭喜你学会了第一种算法,这就是二分查找 。
(二分查找每次都能排除一半的数字,仅当列表是有序时,才能使用二分查找)
公式:待查找项有n个时,我们最多要查找次。
这里补充一下,log是对数,对数是幂的逆运算。log2(n)的意思是:多少个2相乘的结果是n。那么,log10(100)得出的结果是2。10*10=2(2个10相乘的结果为100)。
那么在数组中,我们从0开始编号,设定
备选数组的第一位是low,备选数组的最后一位为high。备选数组最中间的元素为mid
low = 0;
high = length(arr) -1;
那么中间的元素就为:mid = (low + high) / 2;
设定item为我们想要猜到的正确数字,那么我们从数组中间开始猜
key = arr[mid];
if (key < item) {
low = mid +1; //此时我们就把数组中一半的元素都砍掉了,也就是mid前面的数字我们全都拿掉了
}
js完整代码:
const arr = [1, 3, 5, 7, 9];
function binarySearch(arr, key) {
let low = 0; // 实时定义备选项数组的第一个索引
let high = arr.length - 1; // 实时定义备选项数组的最后一个索引
while (low <= high) { // 边缘数字索引值会变,判断左边的索引是不是小于等于右边的索引,以此判断里面是否至少有一个值
let mid = parseInt((high + low) / 2);
if (arr[mid] == key) {
return mid; // 最终返回的值 是正确数字的索引
} else if (key < arr[mid]) {
high = mid - 1;
} else if (key > arr[mid]) {
low = mid + 1;
}
};
return -1;
}
binarySearch(arr, 1);
配了一个精致的解释图(#^.^#) 同居的妹妹都夸我这图好精致。
程序的运行时间
优质的代码都是选择了效率最高的算法,最大限度地减少运行时间和占用空间。
比如我们的数组里有100个数字,用简单查找法(逐个查找)需要猜测100次,简单查找法的次数和列表长度相同。简单查找法的次数(运行时间)叫做线性时间(linear time),表示为O(n)。
而利用二分查找法,100个数字,我们只需要猜7次(或8次)。二分查找法的次数(运行时间)叫做对数时间(英文名不知道是不是叫log time),表示为O(log n)。
参考资料
1. 算法图解 [Aditya Bhargava]