“第一个小于目标值”的语义指最左侧满足 nums[i]
“寻找第一个小于目标值”的语义到底指什么
这个问题容易被误解成“找小于 target 的最大元素”,但实际要的是最左侧的、满足
nums[i] 的索引 i。注意:它不等价于upper_bound或lower_bound的直接调用结果,因为标准库函数默认围绕“等于”或“大于等于”设计,而这里是纯“小于”。如果整个数组都不满足条件(比如所有元素 ≥ target),应返回 -1 或合法边界外的值(如n)。用
std::lower_bound改写实现最简逻辑标准库没提供“小于”的直接迭代器,但可以巧用
lower_bound:它返回第一个 ≥ target 的位置,那么这个位置的前一个元素(如果存在),就是最后一个 的元素——但这不是“第一个”,而是“最后一个”。要找“第一个”,得反向思考:从左往右第一个 。更直接的做法是:对原数组做一次lower_bound,然后检查该位置左边是否还有
- 正确做法是把问题转为:找 第一个满足
nums[i] >= target的位置pos,那么pos - 1就是最后一个- 更稳妥的写法是手写二分,初始化
left = 0,right = n(开区间),循环中若nums[mid] ,说明 <code>mid是候选,记录并往左找更小的索引(right = mid);否则left = mid + 1- 示例:
nums = [1,2,4,4,5], target = 4,期望返回1(nums[1]==2 ,且 <code>nums[0]==1也满足,但第一个是索引 0)——等等,这里发现歧义:题目说“第一个小于”,是指索引最小的那个满足条件的?是的。所以上例答案应是0手写二分时必须注意的三个边界细节
用闭区间
[left, right]或左闭右开[left, right)都可以,但判断逻辑和更新方式必须严格对应。推荐左闭右开,避免死循环:
C++ Code Review Master下载组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 初始化:
int left = 0, right = n;(n是数组长度,right不可达)- 循环条件:
while (left- 核心判断:
if (nums[mid] —— 因为 <code>mid满足条件,它可能是答案,但左边可能还有更小索引也满足,所以收缩右界;否则left = mid + 1- 初始
ans设为 -1,循环结束若仍为 -1,说明无解- 错误高发点:把
right = mid写成right = mid - 1,会导致漏掉mid这个合法候选为什么不能直接用
std::find_if或线性扫描虽然
std::find_if(nums.begin(), nums.end(), [&](int x){ return x 语义清晰,但它时间复杂度是 O(n),失去二分意义。只有在数组有序且规模大(比如 1e6+)、频繁查询时,手写二分的 O(log n) 才体现价值。另外,<code>find_if返回的是迭代器,转换为下标要减begin(),易出错;而手写二分可直接控制返回 -1 或抛异常,更适合封装成工具函数。真正容易被忽略的是:题目隐含要求“数组升序”,但没说是否允许重复。上述二分逻辑对含重复元素的升序数组完全适用;但如果数组降序,必须先反转语义(比如改判
nums[mid] > target并交换左右更新方向),否则结果全错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












