AcWing 算法基础课 二分总结 (持续更新中···)

本文探讨了二分查找算法,包括整数和浮点数的实现策略,特别强调了边界处理在整数二分中的关键,以及如何利用单调性进行非单调问题的解决。同时介绍了二分答案查找的应用,如求解单调区间的最大最小值问题。通过实例和模板演示,深入解析了算法的使用和边界处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分包括二分查找和二分答案

二分查找

二分查找分为整数二分浮点数二分。其实二分和单调性关系不是绝对的,但是二分是永远基于单调性的,可以总结为有单调性的一定可以二分,而能二分的不一定具有单调性,点击这里参考这道题,LeetCode里面有很多非单调用二分查找的

整数二分—需要考虑边界

整数二分需要考虑边界问题,大佬yxc总结的两个万能模板,永远不会错,如下

模板一:如果更新方式是 l = m i d + 1 , r = m i d l=mid+1,r=mid l=mid+1,r=mid,即答案尽量往左边找,那么 m i d mid mid的更新方式是 m i d = ( l + r ) / 2 mid=(l+r)/2 mid=(l+r)/2,向下取整,模板如下

int binary_find(int l, int r)
{
    while(l < r)
    {
        int mid = (l + r) >> 1;//向下取整
        if(check(mid))//check函数根据题目来写
            l = mid + 1;
        else
            r = mid;
    }
    return l;
}

模板二:如果更新方式是 l = m i d , r = m i d − 1 l=mid,r=mid-1 l=midr=mid1,即答案尽量往右边找,那么 m i d mid mid的更新方式是 m i d = ( l + r + 1 ) / 2 mid=(l+r+1)/2 mid=(l+r+1)/2,向上取整,模板如下

int binary_find(int l, int r)
{
    while(l < r)
    {
        int mid = (l + r + 1) >> 1;//向上取整
        if(check(mid))//check函数根据题目来写
            l = mid;
        else
            r = mid - 1;
    }
    return l;
}

但不管是哪种更新方式,循环条件都是while(l<r),这样能保证退出循环的时候一定有l=r

为什么更新方式是 l = m i d , r = m i d − 1 l=mid,r=mid-1 l=midr=mid1 m i d mid mid的更新方式是 m i d = ( l + r + 1 ) / 2 mid=(l+r+1)/2 mid=(l+r+1)/2呢?
举个简单的栗子,当你在 [ 0 , 1 ] [0,1] [0,1]这个区间查找1这个元素,最开始 l = 0 , r = 1 l=0,r=1 l=0,r=1,如果你用 m i d = ( l + r ) / 2 mid=(l+r)/2 mid=(l+r)/2,那么 l l l永远是0, r r r永远是1,而 m i d mid mid也永远是0,查找不到1,陷入了死循环。这样处理就是为了避免死循环

模板题链接:AcWing 789.数的范围

浮点数二分—不需要考虑边界

浮点数二分就没有整数二分那么多的边界问题了,更新方式都是 l = m i d , r = m i d , m i d = ( l + r ) / 2 l=mid,r=mid,mid=(l+r)/2 l=mid,r=mid,mid=(l+r)/2,需要特别注意的是,更新方式里面l和r都不能加1
根据yxc大佬的经验之谈,如果题目叫你保留 n n n位小数,一般要把精度 e p s eps eps设置成 1 e − ( n + 2 ) 1e-(n+2) 1e(n+2),也就是比要保留的小数位数多两位,比如说叫你保留四位小数,精度可以设置成 1 e − 6 1e-6 1e6,以此类推,模板如下:

double binary_find(double l, double r)
{
    double eps = 1e-6;//一般比要求的精度多两位
    while(l + eps < r)
    {
        double mid = (l + r) / 2;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    return l;
}

模板题链接:AcWing 790.数的三次方根

二分答案

二分答案的题目一般是答案在一个区间内,而且答案在这个区间内单调(说起来有点抽象,题做多了就能理解了hh),然后我们就可以借助二分来不断缩小这个区间来查找这个答案

这种题目一般有一个特征,就是叫你求
1、最小的最大值,求最小的xx值就是尽量把答案往左边靠,就是对应上面的模板一
2、最大的最小值,求最大的xx值就是尽量把答案往右边靠,就是对应上面的模板二

话不多说,上模板题:洛谷P2678 跳石头
这道题的答案在一个固定的区间内,也就是 [ 1 , 1000000000 ] [1,1000000000] [1,1000000000]内,而且我们二分答案的时候,答案一定是单调的,因为如果对于一个距离 x x x,我们要移动的石头数目大于 M M M,所以对于所有大于 x x x的值,我们需要移动的时候数目肯定比 x x x对应的多,所以答案一定在小于 x x x的区间内,所以答案单调。而且这道题要我们求最短跳跃距离的最大值,即最大的最小值(最短跳跃距离),对应模板二,写就完事了

另外几道例题:
1、洛谷 P1824 进击的奶牛
2、AcWing 102.最佳牛围栏
3、Max Median
4、Increasing by Modulo
最后两道可有点难度哟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值