<p>左闭右开区间下lower_bound风格二分写法为:while(left < right) { mid = left + (right - left) / 2; if(nums[mid] < target) left = mid + 1; else right = mid; },返回left,对应STL标准且不易越界。</p>

左闭右开区间怎么写 lower_bound 风格的二分
左闭右开([left, right))是 STL 里 lower_bound、upper_bound 的默认区间约定,边界处理更统一,不容易越界。核心是:循环条件用 left ,更新时 <code>right = mid(不是 mid - 1),因为 mid 可能是答案,但右边界不包含它。
常见错误是把 right 初始化成 nums.size() 却在循环里写 right = mid - 1,导致漏查或死循环。
-
left初始为0,right初始为nums.size() - 每次
mid = left + (right - left) / 2,不加1 - 查目标值存在性:循环结束后检查
left - 找第一个 ≥ target 的位置(即
lower_bound):直接返回left,无需额外调整
左闭右闭区间怎么避免 mid 计算溢出和死循环
左闭右闭([left, right])更符合直觉,但容易在 left == right 时陷入死循环——尤其当 mid 更新后没跳过当前值。关键点是:循环条件必须是 left ,且每次更新必须让区间严格缩小。
典型坑是 mid = (left + right) / 2 在大数组下整数溢出;还有 left = mid 或 right = mid 没加减 1,导致 left 和 right 卡住不动。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
mid = left + (right - left) / 2替代(left + right) / 2 - 查
target存在时,if (nums[mid] == target)可直接返回mid - 找左边界(第一个 ≥ target):命中时设
right = mid - 1,否则left = mid + 1 - 循环结束时,
left是第一个 ≥ target 的索引(类似lower_bound),但需校验是否越界
两种区间下 lower_bound 和 upper_bound 的返回值差异
左闭右开区间返回的索引可直接用于 vector::insert 或 erase,语义干净;左闭右闭则需要手动转换——比如 upper_bound 在左闭右闭中返回的是最后一个 ≤ target 的位置,而左闭右开返回的是第一个 > target 的位置,两者差 1。
混用两种逻辑拼接代码时,极易把一个区间的 right 直接传给另一个区间的 right,结果错位。例如把左闭右闭的 right(含)当成左闭右开的 right(不含)用,会少查一个元素。
-
lower_bound在两种区间都返回第一个 ≥ target 的索引,但左闭右闭的返回值范围是[0, nums.size()-1],左闭右开是[0, nums.size()] -
upper_bound在左闭右开返回第一个 > target 的位置(可能等于nums.size()),左闭右闭若按标准实现,应返回最后一个 ≤ target 的位置,需额外处理才能对齐 - STL 所有算法默认左闭右开,自定义二分若要兼容,优先选该风格
什么时候该坚持左闭右开,什么时候用左闭右闭
工程中只要涉及与 STL 容器交互(比如在 vector 中插入、删除、配合 std::distance),一律用左闭右开;纯算法题或教学演示中,左闭右闭更易理解边界含义,但得全程保持一致。
真正容易被忽略的是:同一个项目里不同模块用了不同约定,却没有文档说明。比如封装了一个 binary_search_left 函数,参数是 (arr, l, r, target),但没注明 r 是开还是闭,调用方靠猜,一出错就难定位。
- 函数接口设计时,在参数名里体现约定,如用
end而非right表示开区间终点 - 注释第一行就写清楚:“区间为
[begin, end)” - 测试用例至少覆盖空数组、单元素、全相同、target 不存在于两端等边界

















