二分查找的边界问题
根据查找的结果包含与不包含界值我们大体可以分为两种情况
第一种:每次更新的区间包含右边界,即左闭右闭
模板如下
java:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = (l + r)/2;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
当我们将区间 [l, r] 划分成 [l, mid] 和 [mid + 1, r] 时,其更新操作是 r = mid 或者 l = mid + 1,计算mid时不需要加1,即 mid = (l + r)/2。
第二种:查找的值不包含右边界,即左闭右开
模板如下
java:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = ( l + r + 1 ) /2;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
当我们将区间 [l, r] 划分成 [l, mid - 1] 和 [mid, r] 时,其更新操作是 r = mid - 1或者l = mid,此时为了防止死循环,计算mid时需要加1,即 mid = ( l + r + 1 ) /2。
为什么两个二分模板的mid取值不同?
对于第二个模板,当我们更新区间时,如果左边界l更新为l = mid,此时mid的取值就应为mid = (l + r + 1)/ 2。因为当右边界r = l + 1时,此时mid = (l + l + 1)/2,相当于下取整,mid为l,左边界再次更新为l = mid = l,相当于没有变化。while循环就会陷入死循环。因此,我们总结出来一个小技巧,当左边界要更新为l = mid时,我们就令 mid =(l + r + 1)/2,相当于上取整,此时就不会因为r取特殊值 r = l + 1而陷入死循环了。
作者:lin-shen-shi-jian-lu-k
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/tu-jie-er-fen-zui-qing-xi-yi-dong-de-jia-ddvc/