题目重点:在相邻值不同且边界视为正无穷的合同下,返回一个严格局部最小索引。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练values相邻不等,两端外侧虚拟+∞,strict local min小于存在的两邻;empty None、单元素0,允许任意一个局部最小。
- 相等值/平台、端点是否允许没有完整细则,当前合同明确相邻不同而不声称涵盖所有变体。为保持O(logN)不全量校验前提。
解题路线
- 比较mid与mid+1:若向右下降,右半必包含局部谷底;否则向右上升,左半必包含。相邻不等避免平坡无法判断严格谷底。
- 更精确不变量:搜索区间外两端高度高于相应区间边界,或外侧+∞。下降选择右侧保留左边外高,上升选择左侧保留右边外高,单点时两邻均大即局部最小。
- 算法只返回局部而非全局最小,多个谷底选择由二分路径决定。不可对结果assert等于min(values)作为测试,应该核对其邻居关系。
- 相等允许时可能根本无严格局部最小,例如[2,2];若改为非严格≤,平台可返回但输出合同变了。找严格谷底含plateau需额外扫描/前提,不能继续承诺当前证明。
手动走一遍
[5,3,4,1,2]局部谷底index1或3都合法;[1,2,3]端点0合法,[3,2,1]端点2合法。边界若不允许,单调数组会无解,不能直接复用。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def local_minimum(values):
"""Adjacent values distinct; virtual outside values +infinity; any strict min.
Empty ->None. Assumption not validated to preserve logarithmic query cost.
"""
if not values:return None
left=0;right=len(values)-1
while left<right:
middle=(left+right)//2
if values[middle]>values[middle+1]:left=middle+1
else:right=middle
return left
复杂度
O(logN)比较/O(1)状态,在随机访问与相邻不等前提下。验证相邻不同本身O(N),如果接口承诺输入不可信,总成本含校验而非仅二分。
易错点与追问
容易失分的边界
- 局部最小与全局最小混同。
- 相等平台仍保证strict min存在,明显反例[2,2]。
继续深挖
- 只允许内部局部最小时,怎样报告无解并改变边界证明?
- 磁盘/链表无O(1)中点随机访问时,二分的真实访问成本如何算?
