OCI Senior SWE · Phone Screen Coding

Oracle LC 11 盛水最多容器:双指针为什么只移动短边

从 O(n²) 枚举到 O(n) 双指针,证明移动较短边不会漏掉最优解,并覆盖短数组和零高度。

题目重点:从 O(n²) 枚举到 O(n) 双指针,证明移动较短边不会漏掉最优解,并覆盖短数组和零高度。

题意与假设

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

  • 输入为非负高度数组,两个不同位置组成容器,面积为索引距离乘较低高度;长度不足 2 返回 0。
  • 若出现负高度按训练版报错;原题默认非负。

解题路线

  1. 暴力法枚举所有 i<j,计算 (j−i)·min(h_i,h_j),O(N²) 时间。
  2. 双指针从数组两端开始,计算当前面积后移动较短边。若 h_left≤h_right,固定 left 再把 right 向左移动,宽度变小且短边高度仍不超过 h_left,不可能超过当前面积,所以 left 可安全淘汰。
  3. 若两边等高,移动任一侧都可;当前宽度已最大,固定任一边的更窄组合都不能更优。不断缩小区间至两指针相遇。

手动走一遍

高度 [1,8,6,2,5,4,8,3,7],最佳取下标 1 与 8,面积 7×7=49。若输入 [5,0,5],面积 2×5=10;空数组为 0。

Python 参考实现

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

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

"""LC 11 two-pointer maximum container area."""


def max_container_area(heights: list[int]) -> int:
    if any(height < 0 for height in heights):
        raise ValueError("heights must be nonnegative")
    left, right = 0, len(heights) - 1
    best = 0
    while left < right:
        best = max(best, (right - left) * min(heights[left], heights[right]))
        if heights[left] <= heights[right]:
            left += 1
        else:
            right -= 1
    return best

复杂度

左右指针每步移动一个,O(N) 时间、O(1) 空间;证明依赖面积由较短边限制,不可直接套到其他双指针题。

易错点与追问

容易失分的边界

  • 移动较高边,未能保证被排除组合的面积上界。
  • 把数组高度相加而非取较小高度。
  • 少于两个柱子时仍访问下标。

继续深挖

  • 如果返回构成最大面积的下标对,如何稳定处理并列?
  • 如果容器宽度不再等于索引距离,而是给定非均匀坐标,双指针证明是否仍成立?
✓已复制微信号!