ACM入门之【二分】

原理

基本原理:

二分查找(Binary Search)是一个在有序空间中快速定位答案 的经典算法。

它的基本思想是: 每次把当前区间"对半"切开,保留可能包含答案的一半,丢弃另一半; 重复这个过程,直到区间足够小或者找到答案。
二分的本质: 一个有单调性的搜索空间中寻找满足条件的点。

比如:

  • 有序数组里找元素。

  • 最小化最大值最大化最小值问题。

  • 某个判断条件随着参数变化是单调的(true->false 或 false->true),就可以二分。

简言之: 单调性 + 确定区间收缩方式 → 能二分

二分的常见应用

  • 标准数值二分:在一个升序数组里找一个数,找不到就返回最近的位置。
  • 条件判断二分:定义一个条件 check(x)check(x) 随着 x 的变化是单调的。二分最小的/最大的符合条件的 x。
  • 浮点数二分:如果是连续数轴上找一个实数,比如找根号、找最优值,就需要浮点二分。
  • 二分答案:有些问题本身没有排序,但答案有单调性。
  • 三分:如果目标函数是单峰的(先增后减或先减后增),可以用三分法找最优点。

什么时候能用二分?

条件 解释
1. 有序数据结构 比如升序数组,按位置二分。
2. 单调性质 比如随着某个参数变化,check结果单调变化。
3. 答案有界且单调 比如最小化最大值、最大化最小值。
4. 函数极值问题 如果是单峰,可以用三分。

板子

整数二分的板子代码:

cpp 复制代码
bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;//r=mid不需要加1
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;  //其实就是l=mid 这里加1
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

浮点数二分的板子代码:

cpp 复制代码
bool check(double x) {/* ... */} // 检查x是否满足某种性质

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

习题

标准数值二分 789. 数的范围

标准数值二分 解方程

浮点数二分 790. 数的三次方根

相关推荐
墨染点香7 小时前
LeetCode 刷题【172. 阶乘后的零】
算法·leetcode·职场和发展
做怪小疯子7 小时前
LeetCode 热题 100——链表——反转链表
算法·leetcode·链表
做怪小疯子9 小时前
LeetCode 热题 100——矩阵——旋转图像
算法·leetcode·矩阵
努力学习的小廉9 小时前
我爱学算法之—— BFS之最短路径问题
算法·宽度优先
高山上有一只小老虎10 小时前
构造A+B
java·算法
木头左10 小时前
缺失值插补策略比较线性回归vs.相邻填充在LSTM输入层的性能差异分析
算法·线性回归·lstm
sin_hielo10 小时前
leetcode 2435
数据结构·算法·leetcode
crescent_悦11 小时前
PTA L1-020 帅到没朋友 C++
数据结构·c++·算法
鳄鱼儿11 小时前
密码算法的OID查阅
算法
lxh011311 小时前
螺旋数组题解
前端·算法·js