std::lower_bound是c++ stl中用于在已排序序列中查找第一个不小于(≥)目标值元素的二分查找函数,返回指向该元素的迭代器,时间复杂度为o(log n),要求输入范围必须有序且满足比较器的严格弱序。

为什么 lower_bound 就是你要找的函数
标准库里的 std::lower_bound 干的就是这事:在已排序区间中,找到第一个 不小于(即 ≥)目标值的迭代器。它不关心“等于”还是“大于”,只保证返回位置满足 *it >= target 且前面所有元素都 target。
常见误用是手写二分循环时混淆边界条件,比如把 left = mid 写成 left = mid + 1,导致跳过合法解;而 lower_bound 经过充分测试,行为稳定,且支持随机访问迭代器(vector、array、原生指针等)。
注意:它要求容器/区间必须升序排列,否则结果未定义 —— 不会报错,但返回值毫无意义。
怎么用 lower_bound 获取下标或值
返回的是迭代器,不是下标。想取下标得减去起始迭代器;想取值得解引用。别直接用 int pos = lower_bound(...),那会编译失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 对
vector<int> v = {1,2,2,3,5};</int>,lower_bound(v.begin(), v.end(), 2)返回指向第一个2的迭代器,v.begin() - it是1 - 如果目标不存在(如查
4),它返回指向5的迭代器,下标为4;若目标比所有元素都大(如查6),返回v.end(),此时解引用非法,必须先判断是否越界 - 用法示例:
auto it = lower_bound(v.begin(), v.end(), target);<br>if (it != v.end()) {<br> int idx = it - v.begin();<br> int val = *it;<br>}
手写二分时最容易错的三个地方
自己实现时,边界收缩逻辑稍有偏差就会漏解或死循环。核心在于:当 nums[mid] >= target 时,mid 可能是答案,不能直接排除;而 时,<code>mid 一定不是答案,可以安全跳过。
- 初始右边界必须设为
n(而非n-1),因为答案可能落在末尾之后(即v.end()对应的位置) - 更新逻辑必须是:
if (nums[mid] >= target) right = mid;(不是mid - 1),否则可能丢掉第一个合法位置 - 循环条件用
left ,不用 <code>left ;后者容易在 <code>left == right时陷入死循环,尤其当mid计算用(left + right) / 2(向下取整)时
lower_bound 和手写二分的性能与兼容性差异
两者时间复杂度都是 O(log n),但 lower_bound 在底层做了优化(比如小范围退化为线性查找、分支预测提示),实际运行往往更快。更重要的是,它支持所有满足 RandomAccessIterator 要求的容器,包括 std::deque(虽然不推荐对其二分,但语法合法)、C 数组(lower_bound(arr, arr + n, x))。
手写版本如果硬编码数组长度、忽略迭代器类型,就丧失泛型能力;若没处理空容器或越界,上线后可能 crash。除非你在嵌入式环境禁用 STL,否则没理由重复造轮子。
真要手写,务必用 size_t 或带符号类型统一管理索引,避免和 vector::size() 返回的 size_t 混用导致隐式转换问题 —— 这个坑比逻辑错误更隐蔽。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










