根据判断条件及符合区间所在的位置可以确定所采用的模板
不需要考虑mid+1、mid-1的二分查找模板
y总的模板如下
//模板1
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
//模板2
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
结合各位大佬的总结
AcWing上y总写的总结一下,小伙伴的地下评论总结,以下是归纳整理
AcWing传送门
第一位大佬的原话
无意间發现了这个网站真是如入宝山呀,在这裡也分享一点心得,希望能对大家有点帮助。
虽然这模版真的是非常好用,但是每次在决定那个 check 函数时总是让我想破头,
因为一不小心写反就找不到了,一路跌跌撞撞后稍稍有点心得,如果有错还请各位高手指正假设有一个总区间,经由我们的 check 函数判断后,可分成两部分, 这边以o作 true,…作 false 示意较好识别
如果我们的目标是下面这个v,那麽就必须使用模板 1
…vooooooooo
假设经由 check 划分后,整个区间的属性与目标v如下,则我们必须使用模板 2
oooooooov…
所以下次可以观察 check 属性再与模板1 or 2 互相搭配就不会写错啦
v 的属性,本身也要是 true,也就是 check 为 true 的左边界或是右边界(前提是目标一定是找得到的,不然跳出回圈后,必须加上额外判断)。
第二位大佬的原话
第一种找目标值在数组中最 左 边出现的位置
第二种找目标值在数组中最 右 边出现的位置
我的总结
区分点 | 版本1 | 版本2 |
---|---|---|
将区间[l, r]划分成 | [l,mid],[mid+1,r] | [l,mid-1],[mid,r] |
check条件填写 | 让要找的数和其右侧变量使得check为true | 让要找的数和其左侧遍量使得check为true |
找目标值在数组中 | 最 左 边出现的位置 | 最 右 边出现的位置 |