二分法模板

二分法模板
整数型二分

{
    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
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上一篇:java实现二维码的生成


下一篇:浅析为什么char类型的范围是 -128~+127