题目重点:从 O(n²) 枚举到 O(n) 双指针,证明移动较短边不会漏掉最优解,并覆盖短数组和零高度。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 输入为非负高度数组,两个不同位置组成容器,面积为索引距离乘较低高度;长度不足 2 返回 0。
- 若出现负高度按训练版报错;原题默认非负。
解题路线
- 暴力法枚举所有 i<j,计算 (j−i)·min(h_i,h_j),O(N²) 时间。
- 双指针从数组两端开始,计算当前面积后移动较短边。若 h_left≤h_right,固定 left 再把 right 向左移动,宽度变小且短边高度仍不超过 h_left,不可能超过当前面积,所以 left 可安全淘汰。
- 若两边等高,移动任一侧都可;当前宽度已最大,固定任一边的更窄组合都不能更优。不断缩小区间至两指针相遇。
手动走一遍
高度 [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) 空间;证明依赖面积由较短边限制,不可直接套到其他双指针题。
易错点与追问
容易失分的边界
- 移动较高边,未能保证被排除组合的面积上界。
- 把数组高度相加而非取较小高度。
- 少于两个柱子时仍访问下标。
继续深挖
- 如果返回构成最大面积的下标对,如何稳定处理并列?
- 如果容器宽度不再等于索引距离,而是给定非均匀坐标,双指针证明是否仍成立?
