SDE / New Grad · Coding

Amazon Coding:先增后减数组,二分找最大峰值

用相邻斜率排除半区,解释端点、平台以及一般局部峰与全局最大差别。

题目重点:用相邻斜率排除半区,解释端点、平台以及一般局部峰与全局最大差别。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练合同严格递增后严格递减,允许单元素和单调数组退化;平台不是本代码前提。
  • 不在O(log n)例程里扫描全数组验证单峰,面试先确认前提。

解题路线

  1. 比较mid和mid+1:上升意味着峰在mid右边,lo=mid+1;下降意味着峰在mid或左边,hi=mid。半区始终保留唯一全局峰。
  2. strict bitonic合同保证上升侧无更早下降,下降侧无后续更高峰;每次缩短区间直到一个下标。mid<hi所以访问mid+1合法。
  3. 任意数组同写法最多保证某个局部峰,不能保证全局最大。例如[10,1,2,3]可返回3而漏10。题面从“有峰”到“单峰”的区别是证明关键。
  4. 允许平顶应说明是否只有一个最大平台和其位置政策;任意弱单峰可能有低处平段,遇到相等不能安全判断方向,最坏可退化线性。

手动走一遍

题目给数组峰值9、下标4。训练[1,2,3]返回2,[3,2,1]返回0,[7]返回0。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def peak_index(values):
    """Nonempty strictly increasing then strictly decreasing array, endpoints allowed."""
    if not values:
        raise ValueError("empty array")
    lo,hi=0,len(values)-1
    while lo < hi:
        mid=(lo+hi)//2
        if values[mid] < values[mid+1]:
            lo=mid+1
        else:
            hi=mid
    return lo

复杂度

O(log n)时间、O(1)空间;检查严格单峰前提需要O(n)。

易错点与追问

容易失分的边界

  • 拿一般局部峰算法保证全局最大。
  • 相等时无论什么平台都丢右半区。
  • mid+1越界。

继续深挖

  • 若平台允许且要最左最大值?
  • 未知数据怎样检测前提失效?
  • 外部随机访问API怎样算查询次数?
✓已复制微信号!