优先使用std::lower_bound因其底层经过充分测试、边界和迭代器处理更健壮;手写易出错,如边界更新遗漏、mid计算溢出;需确保数组有序,返回首个≥target的迭代器,须与end()比较判断是否找到。

std::lower_bound 为什么比手写二分更值得优先用
绝大多数情况下,直接调用 std::lower_bound 是最稳妥的选择——它底层是经过充分测试的二分实现,处理边界、迭代器类型、自定义比较逻辑都更健壮。手写容易在 left/right 边界更新时漏掉一个元素,或在 mid 计算时整数溢出(尤其在大数组中)。
使用前提:数组必须已升序排列(或按指定比较规则有序)。若无序,先排序或改用 std::find。
-
std::lower_bound返回第一个 ≥ target 的迭代器;找不到则返回end() - 要判断是否找到,必须和
end()比较,不能只看值是否等于 target(因为可能越界解引用) - 支持自定义比较函数,比如降序数组要用
std::greater<int>()</int>
std::vector<int> arr = {1, 3, 5, 7, 9};
auto it = std::lower_bound(arr.begin(), arr.end(), 5);
if (it != arr.end() && *it == 5) {
std::cout << "found at index " << (it - arr.begin()) << "\n";
}手写二分时最容易错的三个地方
不是逻辑写不对,而是细节踩坑导致死循环或越界。常见错误现象:while (left < right) 卡住不动、mid 算出负数、查不到最后一个元素。
- 区间定义必须统一:推荐闭区间
[left, right],初始化right = size - 1;更新时right = mid - 1和left = mid + 1对称,不易漏 -
mid必须写成left + (right - left) / 2,避免(left + right)溢出(尤其int数组索引接近INT_MAX时) - 循环退出条件选
left <= right,否则闭区间会漏判left == right的情况
int binary_search(const std::vector<int>& arr, int target) {
int left = 0, right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1; // not found
}搜索重复元素时,std::lower_bound 和 std::upper_bound 怎么配合用
当数组含重复值(如 {2,4,4,4,6}),单靠 std::lower_bound 只能定位第一个 4;要找全部,需搭配 std::upper_bound 获取第一个 > target 的位置。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
-
std::lower_bound→ 第一个 ≥ target 的位置 -
std::upper_bound→ 第一个 > target 的位置 - 两者差值就是 target 出现次数;区间
[lower, upper)内所有元素都等于 target - 若
lower == upper,说明没找到
auto lo = std::lower_bound(arr.begin(), arr.end(), 4); auto up = std::upper_bound(arr.begin(), arr.end(), 4); int count = up - lo; // 3 in this case
std::binary_search 只适合“存在性判断”
std::binary_search 返回 bool,不告诉你位置。它内部调用 std::lower_bound,但丢弃了迭代器结果。性能上和 lower_bound 差不多,但用途受限。
- 仅适用于“这个数在不在数组里”的场景,比如去重前快速校验
- 如果后续还要取值或算下标,硬用
std::binary_search再搜一遍就浪费了一次遍历 - 它不提供
upper_bound那种“大于”语义,也无法处理重复范围查询
真正需要下标或迭代器时,别图省事,直接用 std::lower_bound 更省事也更灵活。

















