二分查找找第一个小于 target 的元素,本质是找右边界左侧位置;实际等价于 lower_bound 行为,即 l 最终停在第一个 ≥ target 的位置。

二分查找找第一个小于 target 的元素,本质是找右边界左侧位置
直接说结论:这不是标准二分查找的常见变种,但可以复用 lower_bound 或手写逻辑——关键不是“小于”,而是“最后一个满足 arr[i] 的索引”。它等价于 <code>lower_bound 返回位置的前一个位置,前提是该位置合法。
用 std::lower_bound 快速得到答案(推荐)
std::lower_bound 返回第一个 ≥ target 的迭代器,所以它的前一个位置(如果存在)就是最后一个 target 的元素。这是最安全、最不易出错的方式。
实操建议:
- 先调用
std::lower_bound(arr.begin(), arr.end(), target) - 检查返回迭代器是否等于
arr.begin():若是,说明所有元素都 ≥target,不存在小于target的元素 - 否则,
prev(it)对应的值就是目标;对应索引为it - arr.begin() - 1
示例:
立即学习“C++免费学习笔记(深入)”;
vector<int> arr = {1, 2, 4, 4, 5, 7};
auto it = lower_bound(arr.begin(), arr.end(), 4); // 指向第一个 4(索引 2)
if (it != arr.begin()) {
int idx = it - arr.begin() - 1; // 得到索引 1,arr[1] == 2,确实是最后一个 < 4 的元素
}手写二分时容易踩的边界坑
手写必须明确:搜索区间定义为 [left, right] 还是 [left, right),且循环终止条件、更新方式必须严格匹配。常见错误是越界或漏判边界。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
推荐使用左闭右开区间 [l, r):
- 初始
l = 0,r = arr.size() - 循环条件为
l - 每次
mid = l + (r - l) / 2,若arr[mid] ,说明 <code>mid可能是候选,但还要往右找更大下标 →l = mid + 1 - 否则
r = mid - 退出后,
l - 1就是最后一个满足arr[i] 的索引(需检查 <code>l > 0)
注意:这里 l 最终停在第一个 ≥ target 的位置,和 lower_bound 行为一致 —— 所以手写逻辑其实就是在复现它。
数组为空、全 ≥ target 或全
这三类边界情况必须显式判断,否则 prev(it) 或 l - 1 会越界。
- 空数组:直接返回无效标识(如 -1)
- 所有元素 ≥
target:lower_bound返回begin(),此时无解 - 所有元素 target:
lower_bound返回end(),此时答案是最后一个索引size() - 1
手写版本中,l == 0 表示无解;l == arr.size() 表示全满足,答案为 size() - 1。
真正麻烦的不是算法逻辑,而是对 “不存在” 场景的统一建模——返回 -1?抛异常?还是用 optional<int>?选哪种取决于你调用它的上下文,但别默认假设一定存在。

















