推荐使用的二分查找模板

14 篇文章 2 订阅

概述

本文和前面标准二分查找模板,https://blog.csdn.net/justidle/article/details/104303389,有比较大的不同,在写二分查找的时候,建议使用本文的方式。

二分查找本质

如下图所示,我们将一个 [l, r] 区分分为两个区域。只要我们能将一个区域分为两步部分,那么我们即可以查找红色的边界点,也可以查找绿色的边界点。二分绿色或者红色点,就是我们两个不同模板。

二分要素

一个 check 函数

函数原型为 bool check(int x),该函数用于检查 x 是否满足某种属性。

bool check(int x) {
    ......
}

三个变量

1、左边界(left)。用于描述查找区间的左边界。

2、右边界(right)。用于描述查找区间的右边界。

3、中间值(mid)。通过左边界和右边界计算而得。在二分查找中,使用这个 mid 数值验证是否满足题目的条件,也就是调用 check(mid)。

循环条件

当 left < right 成立的时候,进行二分查找。

区间缩小

1、当 check() 函数成立的时候,缩小边界,即 right = mid 或者 left = mid。

2、当 check() 函数不成立的时候,缩小边界,即 left = mid+1 或者 right = mid-1。

具体使用哪种模板在下面讨论。

返回值

左边界。即 left 为二分查找的结果。

模板代码

模板一

二分出第一个图的红色点。我们将 [l, r] 这个区域划分为 [l, mid-1], [mid, r] 这两个区域。

我们知道二分的核心是以 mid 为边界,判断中间值是否满足题目的某种性质,本模板是 check(mid) 这个函数满足红色区域的性质。假设 check() 满足红色区域性质,那么 mid 一定是在红色区域里,如下图所示,那么答案自然在 [mid, r] 这个区域,区域更新方式就是  l=mid。

假设 check() 不满足红色区域性质,那么 mid 一定是在绿色区域里,如下图所示,那么答案自然在 [l, mid-1] 这个区域,区域更新方式就是  r=mid-1。

参考代码如下:

int bsearch_2(int l, int r) {
    while (l < r) {
        int mid = l+((r-l+1)>>1);
        if (check(mid)) {
            l = mid;
        } else {
            r = mid - 1;
        }
    }
    return l;
}

注意:mid 的计算方法和模板一是不相同的。

模板二

二分出第一个图的绿色点。我们将 [l, r] 这个区域划分为 [l, mid], [mid+1, r] 这两个区域。

我们知道二分的核心是以 mid 为边界,判断中间值是否满足题目的某种性质,本模板是 check(mid) 这个函数满足绿色区域的性质。假设 check() 满足绿色区域性质,那么 mid 一定是在绿色区域里,如下图所示,那么答案自然 [l, mid] 这个区域,区域更新方式就是  r=mid。

假设 check() 不满足绿色区域性质,那么 mid 一定是在红色区域里,如下图所示,那么答案自然在 [mid+1, r] 这个区域,区域更新方式就是  l=mid+1。

参考代码如下:

int bsearch_1(int l, int r) {
    while (l < r) {
        int mid = l+((r-l)>>1);
        if (check(mid)) {
            r = mid;    // check()判断mid是否满足性质
        } else {
            l = mid + 1;
        }
    }
    return l;
}

口诀

1、先写 check() 函数。

2、在随便套用一种二分查找模板。

3、确定使用哪种区间划分方案,修改代码。

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值