OCI SWE · Phone Screen Coding

Oracle CPU 占用率找峰值:单峰二分与多峰边界

从线性扫描基线到严格单峰数组二分,解释多峰时为何无法无条件保留 O(log n) 的全局最大保证。

题目重点:从线性扫描基线到严格单峰数组二分,解释多峰时为何无法无条件保留 O(log n) 的全局最大保证。

题意与假设

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

  • 训练二分版数组严格先增后减,峰可在边界;无相等平台。题目只说一个 peak,严格单峰是为保证二分正确的额外约定。
  • 多峰版要求全局最大值位置,若并列取最早位置;空数组报错。

解题路线

  1. 任意数组先做线性基线,逐项维护最大值与位置,O(N) 且不依赖形状。
  2. 严格单峰时比较 values[mid] 与 values[mid+1]:若上升,峰位于右侧含 mid+1;否则位于左侧含 mid。每次保留峰所在半区。
  3. low==high 时即峰值下标。归纳不变量是唯一峰一直位于 [low,high];严格单峰使局部斜率能决定唯一峰方向。
  4. 任意多峰时局部上升只能说明右边存在局部峰,不能排除左边有更高峰;若没有其他结构保证,必须扫描以找全局最大。

手动走一遍

[1,4,7,5,2] 比较中点 7 与 5 后保留左半,最终下标 2。多峰 [9,1,2,3] 在中间右侧上升,却全局最大在左端,照搬单峰二分会错。

Python 参考实现

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

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

"""Find the unique peak of a strictly increasing-then-decreasing sequence."""


def unique_peak_index(values: list[int]) -> int:
    if not values:
        raise ValueError("values must be nonempty")
    low, high = 0, len(values) - 1
    while low < high:
        middle = (low + high) // 2
        if values[middle] < values[middle + 1]:
            low = middle + 1
        else:
            high = middle
    return low


def global_max_index(values: list[int]) -> int:
    if not values:
        raise ValueError("values must be nonempty")
    return max(range(len(values)), key=lambda index: values[index])

复杂度

严格单峰找峰 O(log N) 时间、O(1) 空间;任意多峰找全局最大 O(N) 时间、O(1) 空间。若仅要任一局部峰,可有不同的二分问题,不能与全局最大混同。

易错点与追问

容易失分的边界

  • 把一个局部峰与全局最大峰混为一谈。
  • 有平台或噪声时仍直接宣称严格单峰二分正确。
  • 把 CPU 采样原始噪声数据当成已满足单峰的聚合数组。

继续深挖

  • 若有平顶区间,如何定义返回最左、最右或任意峰?
  • 若允许少量噪声而总体单峰,如何在正确性与近似之间取舍?
✓已复制微信号!