二分法模板
整数型二分
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
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;
}
整数域二分
二分模板一共有两个,分别适用于不同情况。
算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。
版本1
当区间[l, r]的更新操作是r = mid; l = mid + 1;时,计算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;
}
解读
我们要在下面一串数中用上面的二分查找代码查找 1111
第一次查询,(l+r)/2=4(l+r)/2=4,查到 88 ,是小于 1111 的,于是更新,l=4+1=5l=4+1=5
第二次查询,(l+r)/2=6(l+r)/2=6 ,查到1212 ,是大于1111的,于是更新,r=mid=6r=mid=6
第三次查询,(l+r)/2=5(l+r)/2=5 ,查到1010,是小于1111的,于是更新,l=5+1=6l=5+1=6
最终得到结果为1212 。12是我们查找到这一串数中,大于等于11(查找数)中最小值。
我们可以得到一个结论:以上二分模板用来解,最大值最小问题。
版本2
当区间[l, 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;
}
解读
我们要在下面一串数中用上面的二分查找代码查找 1111
第一次查询,(l+r+1)/2=4(l+r+1)/2=4,查到 88 ,是小于 1111 的,于是更新,l=4l=4
第二次查询,(l+r+1)/2=6(l+r+1)/2=6,查到 1212 ,是大于 1111 的,于是更新,r=6−1=5r=6−1=5
第三次查询,(l+r+1)/2=5(l+r+1)/2=5,查到 1010 ,是小于 1111 的,于是更新,l=5l=5
最终得到结果为1010 。10是我们查找到这一串数中,小于等于11(查找数)中最大值。
我们可以得到一个结论:以上二分模板用来解,最小值最大问题。
二分答案
二分答案与二分查找类似,即对有着单调性的答案进行二分,大多数情况下用于求解满足某种条件下的最大(小)值。
作者:Chicago
链接:https://www.acwing.com/blog/content/91/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。