终结条件为
根据if (check(mid)) 条件成立,判断答案在左区间还是右区间,如果答案在左区间并且mid也可能是答案,那么就要按模板1[l, mid], [mid + 1, r]来划分;如果答案在右区间并且mid也可能是答案,那么就要按模板2[l, mid - 1], [mid, r]来划分。
注意check(mid)要能够保证将答案分在两侧,例如找最后一个小于等于target的数,如果条件写的是target <= nums[mid],那么如果判断为真,你的目标既有可能在mid的左侧,也有可能在mid的右侧,是没有划分效果的。如果取nums[mid] <= target则成立。
- 版本1
最大值最小问题,第一个>=target的元素
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
int bsearch_1(int l, int r)
{
while (l < r)
{
// 两个int相加减会溢出 中间加个长整型常量
int mid = l + 0ll + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
- 版本2
最小值最大问题,最后一个<= target的元素
//区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用,其更新操作是r = mid - 1或者l = mid。
因为r更新为mid-1,如果mid仍然计算下取整,则l和r差1时大者永远取不到,会死循环,因此计算mid时需要加1。
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + 1ll + r >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
二分答案
https://www.cnblogs.com/lcosmos/p/9438705.html
https://www.cnblogs.com/luoxn28/p/5767571.html
旋转数组的二分查找
https://www.geeksforgeeks.org/the-ubiquitous-binary-search-set-1/