跳到正文
第 11 题中等

盛最多水的容器

Container With Most Water

给定一排柱子的高度,选两根柱子与 x 轴围成容器,求能装下的最大水量。

在力扣中练习

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

 

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

 

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

解题思路

主解法

双指针 · 移动较矮的一侧

宽度从最大开始,每次舍弃较矮的那根柱子

暴力枚举所有柱子对是 O(n²)。双指针从最左、最右开始,宽度最大,然后逐步向内收。

当前面积由较矮的那根柱子决定:min(height[left], height[right]) × 宽度。

如果移动较高的一侧,宽度一定变小,而高度仍被较矮的那根限制,面积不可能变大;所以只能移动较矮的一侧,才可能遇到更高的柱子。

自拟主例 [2,7,3,8,4,6]:初始面积 2×5=10;移动 2 后,7 和 6 围出 6×4=24,这就是最大面积。

分步图解

宽度 5 × 较矮高度 2 = 10;当前最大 10。

面积
10
best
10
heightleft = 0 · right = 5
最大面积 10高度 220高度 771高度 332高度 883高度 444高度 665leftright

面积 = 较矮的柱子 × 两柱间距

1 / 3
先移动较矮的 2,再移动较矮的 6;较高的一侧一直保留。

每次移动都排除了一根不可能再成为最优边界的柱子,所以总移动次数是 O(n)。

分步图解

宽度 2 × 较矮高度 7 = 14;当前最大 24。

面积
14
best
24
heightleft = 1 · right = 3
最大面积 14高度 220高度 771高度 332高度 883高度 444高度 665leftright

面积 = 较矮的柱子 × 两柱间距

1 / 3
宽度缩小到 2 时,左右都是高度 7;面积 14 仍小于之前的 24。

时间 O(n),空间 O(1)。

时间 O(n)空间 O(1)

易错点

  • 移动较高的一侧:宽度变小且高度仍受较矮柱子限制,会错过最优解。
  • 用两根柱子的高度之和或较大值算面积:容器高度由较矮的那根决定。
  • 忘记宽度是 right-left 而不是 right-left+1:下标差就是柱子间距。
对照解法

暴力枚举 · 所有柱子对

枚举每一对柱子,直接算面积

仅作对照,正确但 O(n²),n 较大时会超时;主解法的双指针是 O(n)。

最直观的写法:固定左柱子 i,枚举右柱子 j,面积是 min(height[i], height[j]) × (j-i),取最大值。

它不需要证明“移动较矮一侧”的正确性,适合用来验证双指针的结果;但两层循环是 O(n²),不能作为提交方案。

  1. 1i 从 0 到 n-1。
  2. 2j 从 i+1 到 n-1。
  3. 3用 min(height[i], height[j]) × (j-i) 更新 best。
时间 O(n²)空间 O(1)

易错点

  • 内层 j 从 i 开始:会重复计算同一对柱子,还会把宽度 0 算进去。
  • 用较大的高度算面积:容器会被较矮的一侧截断。

代码与演示

主解法配有图解;对照解法用于比较思路、复杂度或实现方式。

演示输入height = [2,7,3,8,4,6]

left = 0,right = 5;先看最外侧两根柱子。

left
0
right
5
heightleft = 0 · right = 5
面积 10高度 220高度 771高度 332高度 883高度 444高度 665leftright

面积 = 较矮的柱子 × 两柱间距

1 / 7
查看 C++ 代码

延伸阅读

  • 双指针的合法性来自“排除不可能更优的边界”,不是随便移动;每一步都要能说清排除了什么。
  • 同类题:接雨水(42)用左右最大值决定每列能接多少水,也是从两端向中间收。