手撕:二分查找及其边界变体。
五个经典回答示范
「标准二分是找等于 target 的任意位置;找左边界用 lower_bound 语义:找到第一个大于等于 target 的位置,收缩条件是 nums[mid] < target 时右移 left,否则 right 收到 mid。判断左界值是否等于 target 决定存在性。全程用 left + (right-left)/2 防溢出。」
function lowerBound(nums, target) { let l = 0, r = nums.length; while (l < r) { const m = l + Math.floor((r - l) / 2); if (nums[m] < target) l = m + 1; else r = m; } return l; } 右边界 = upperBound - 1,upperBound 只是条件换成 <=。这个半开区间写法不会死循环,闭区间写法则要注意 mid 上取整。
旋转数组找目标:先判断哪半有序,再判断 target 在不在有序半区内决定收缩方向。求峰值:nums[mid] 与邻居比较上坡方向收缩,O(logn)。二分答案:答案空间单调时二分答案值、用 check 函数验证——配送最少时间、吃香蕉速度这类题的通解。能讲二分答案的适用条件,是区分度所在。
必测:空数组、单元素、target 小于全部、大于全部、等于首、等于尾、数组全相同值、target 不存在但落在中间。左边界版要专门测重复元素——[5,7,7,8,8,10] 找 8 左右界。死循环的根源是区间不变量被破坏,写之前先声明区间含义再动笔。
错误一:mid = (l+r)/2 溢出——大数组下 l+r 超过 int 上限。错误二:收缩写成 l = m 死循环——当区间剩两个元素且条件不满足时 mid 永远不动。错误三:左右界混用大于等于与大于,查了半天查不出 off-by-one。点评:二分是边界题不是思路题,能一次写对靠的是纪律不是聪明。
- 打开 模拟练习,选择「算法工程师」方向,限时 3 分钟作答本题。
- 对照上方答题框架,逐点检查:哪些要素没覆盖、哪里表达啰嗦。
- 用自己项目的真实经历替换框架中的占位内容,重讲一遍并录音回听。
这类题在真实面试中常被追问细节,
建议进入限时模式练一遍。