AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

最简二分模板——秒杀95%的二分题

作者: 作者的头像   捡到一束光 ,  2019-07-18 22:12:35 ,  所有人可见 ,  阅读 4220


41


55

原文链接: https://blog.csdn.net/qq_43827595/article/details/90292248

二分模板
1.循环必须是l < r
2.if判断条件看是不是不满足条件, 然后修改上下界
3.若if else后是r = mid - 1,则前面mid 语句要加1
4.出循环一定是l == r,所以l和r用哪个都可以

二分只有下面两种情况
1:找大于等于给定数的第一个位置 (满足某个条件的第一个数)
2:找小于等于给定数的最后一个数 (满足某个条件的最后一个数)


QQ图片20190718221913.png


二分流程.png


// 判断条件很复杂时用check函数,否则if后直接写条件即可
bool check(int mid) {
    ...
    return ...;
}

// 能二分的题一定是满足某种性质,分成左右两部分
// if的判断条件是让mid落在满足你想要结果的区间内

// 找满足某个条件的第一个数  即右半段
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;
}

// 找满足某个条件的最后一个数  即左半段
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;
}


注释:
 模板2求mid时要加一,因为除以2默认是下取整
 比如红色区域二分到l = 3, r = 4,目标位置是4,那么 若不加一,则mid永远无法到4

经典例题 leetcode 69:x的平方根

实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2

示例 2:

输入: 8
输出: 2

说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。

class Solution {
public:
    int mySqrt(int x) {
        int l = 0, r = x;
        while (l < r) {
            // 两个int相加减会溢出 中间加个长整型常量
            // 少用乘法,用除法可以防止溢出
            int mid = l + 1ll + r >> 1; 
            if (mid  <= x / mid) l = mid;  
            else r = mid - 1;
        }
        return l;
    }
};

16 评论


用户头像
一加一_8   2024-04-28 23:23         踩      回复

太棒啦,一下子就不迷糊了


用户头像
V-bear   2023-12-18 23:06         踩      回复

最大值第一个,最小值第二个,第一个的索引从右边来,第二个的索引从左边来


用户头像
摘樱桃   2022-01-24 20:42         踩      回复

感谢大佬hhh,明白了


用户头像
冰冰的帅气男友   2021-07-03 19:01         踩      回复

int mid = l + 1ll + r >> 1;这是什么意思


用户头像
玛卡巴卡呀   2021-03-30 17:44         踩      回复

二分使用的条件一定是一个有序的数组嘛

用户头像
码   2021-07-22 08:52         踩      回复

不一定,但是有序一定可以二分.


用户头像
nestle   2020-07-12 22:21         踩      回复

“if的判断条件是让mid落在满足你想要结果的区间内” ,这句话真的是画龙点睛,让我醍醐灌顶,终于搞明白为什么两个看上去差不多的代码能够分别找到左右边界了。


用户头像
Zh1995   2019-10-22 21:35         踩      回复

除法是防止什么溢出的?

用户头像
捡到一束光   2019-10-22 23:56         踩      回复

防止mid * mid超出int的范围,所以用除法来避免


用户头像
隐秀_   2019-08-04 12:52         踩      回复

### 强


用户头像
song666   2019-07-28 22:13         踩      回复

ORZOTZ


用户头像
robot_1   2019-07-28 08:08         踩      回复

nb!


用户头像
bigbrox   2019-07-25 20:27         踩      回复

感谢


用户头像
秦淮岸灯火阑珊   2019-07-22 08:44         踩      回复

(๑•̀ㅂ•́)و✧棒!


用户头像
达达   2019-07-22 08:33         踩      回复

感谢分享!!!!非常清晰,看完终于明白二分怎么用了!!!


用户头像
M_Fish   2019-07-19 21:34         踩      回复

%%%


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息