小白讲故事,每日都精彩。
啪啦啪啦,小白批试卷。长得帅满分,长得俏满分,会说话满分。
前提:摆在小白面前是排好序的试卷
目标:调皮的小白想从中挑出漂亮小姐姐嬴政的试卷
聪明的你会通过什么方式快速帮小白找到?
没错今日小白给大家带来有趣的二分法。(小白就喜欢二八分偏偏头)
从试卷思考
小白也是去过嵩山,练过武功,常常看《赌神》。就希望有朝一日,练成千王之手,在江湖有一席地位。(此处省略一万字。。。)
小白一出手,就知有没有。摸出一个张李四。(人在江湖漂,哪有不失手的)
别灰心!我们知道嬴政大美女在李四的后边。再来次,从后边摸一张。哦豁,摸出个姚明。(长得高得人就爱出风头)
小白原谅你这次。现在还剩两张试卷,那可是百分百命中。哈哈~~~
费劲千辛万苦,总算揭开了大美女嬴政的面纱。
从规模上寻找最差和最好情况
小白以为自己已经是高高高手,自信能一次命中。(最好情况)
然而,现实是残酷的。找无可找,才得到目标。(最坏情况)
那这个过程是怎样的?
假设我们当前规模是1000,那么需要查多少次?
其实我们可以用1000除以2,直到剩下1。那么需要多少次?
我们知道2的9次方等于512,2的10次方等于1024,那么我们求得x就应该介于9次方到10次方之间。
那么我们就推导T(n)公式了,如图:
(提示:└是值下限,相当于Math.floor,就这么理解吧)
如果你不相信,小白就跟你理论,哪个好看哪个请客。通过一个数N是否是2的K次幂的角度论证。论证如下:
从例子到抽象
从之前我们的将栗子中抽象成代码:
function bSearch(A, x)
A: 是数组
x:是要查找的数
结果: 返回x的位置,存在
返回-1,不存在
复制代码
看看我们是查找22的过程。
(l左边界,r右边界,g猜想)
第一次:我们通过左边界和右边界取中间值(1),Math.floor((l+r)/2),g得到坐标5,也就是33
对比:22在33的左边,所以右边界r = 5-1 = 4
第二次: 重复(1)的操作,g得到坐标2,也就是19
对比:22在19的右边,所以右边界了= 2+1 =3
第三次: 重复(1)的操作,g得到坐标3,也就是22,得到结果。
最后小白献上代码一份:
function bSearch(n, x){
let l = 0, // 查询范围左边界
r = n.length, // 查询范围右边界
guess; // 猜想位置
while(l <= r){
guess = Math.floor((l+r)/2);
// 循环不变式
// guess等于l,r中间位置
if(n[guess] === x) return guess;
if(n[guess] > x){ // x在n[guess]的左边
r = guess - 1
}else{ // 否则就在右边
l = guess + 1
// 循环不变式:新的查找范围
}
}
return -1
}
复制代码
今日一题
写一个函数,将字符串除了最后的四位,其他都变成#
maskify("4556364607935616") == "############5616"
maskify( "64607935616") == "#######5616"
maskify( "1") == "1"
maskify( "") == ""
// "What was the name of your first pet?"
maskify("Skippy") == "##ippy"
maskify("Nananananananananananananananana Batman!") == "####################################man!"
复制代码