参考闫学灿大佬视频讲解和模板:
https://www.acwing.com/blog/content/31/
二分模板
算法思路:假设目标值在闭区间[l, r]中,每次将区间长度缩小一半,当l = r 时,就找到了目标值。
模板一
mid = l + r >> 1, (下取整)
if mid是绿色,分界点target在mid左侧,可能包括mid, [l,r]->[l,mid], r = mid
else mid是红色,分界点target在mid右侧,不包括mid , [l,r]->[mid+1,r], l = mid + 1
当我们将区间[l, r]划分成[l, mid], [mid + 1, r]时,其更新操作是 r = mid 或者 l = mid + 1。
C++代码模板:
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;
}
模板二
mid = l + r +1 >> 1,(上取整)
if mid 是红色,分界点target在mid 右侧,可能包括mid, [l,r]->[mid,r], l = mid
else mid 是绿色, 分界点target在mid 左侧, 不包括mid, [l,r]->[l,mid - 1] r = mid - 1
注意:
如果模板二用mid = l + r >> 1,(下取整)
当l = r - 1, mid = l + r >>1 == 2l + 1 >>1 == l
if mid 是红色,[l,r]->[mid,r] ->[l,r],死循环。
当我们将区间[l, r]划分成[l, mid - 1] 和[mid, r]时,更新操作是 r = mid - 1或者 l = mid,此时为了防止死循环,计算mid 时要加1。
C++代码模板:
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;
}
感谢分享
感謝分享 👍