Appearance
盛最多水的容器
更新: 7/4/2026 字数: 0 字 时长: 0 分钟
题目描述
给定一个长度为 的整数数组 height,其中 height[i] 表示第 i 根垂直线段的高度(线段的两端点为 (i, 0) 和 (i, height[i]))。找出其中的两条线段,使它们与 x 轴共同构成的容器可以容纳最多的水,返回这个最大容水量。
容器不能倾斜。由两条线段 i < j 构成的容器容量为:
即「较矮的那条边的高度」乘以「两条边之间的水平宽度」——因为水会从较矮的一侧溢出。
输入:
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]输出:49(选下标1(高 8)与下标8(高 7),面积 =min(8,7) × (8-1) = 7 × 7 = 49)

思路拆解
暴力解法:枚举所有两两组合
最直接的想法是枚举每一对线段 (i, j),逐个算出面积并取最大值。思路无脑,一定正确,但需要两层循环,时间是 ,数据量大时会超时。
点击展开暴力解法
js
function maxArea(height) {
let best = 0
for (let i = 0; i < height.length; i++) {
for (let j = i + 1; j < height.length; j++) {
const area = Math.min(height[i], height[j]) * (j - i)
best = Math.max(best, area)
}
}
return best
}最优解法:双指针从两端向内收缩
关键观察:一开始把两条边放在数组最左和最右,此时宽度是最大的。 之后无论怎么移动,宽度只会变小。既然宽度只减不增,想让面积有机会变大,就只能寄希望于「较矮的那条边被换成更高的边」。
于是核心决策来了——每次应该移动较矮的一侧,还是较高的一侧?
核心思路
面积由较矮的边决定。如果移动较高的那条边,短板高度不会上升(顶多不变),而宽度一定变小,面积必然不增——这一步毫无意义。反过来,移动较矮的边,才有机会换来更高的短板,从而弥补宽度的损失。所以每一步都移动较矮的一侧。

为什么这样不会漏掉最优解? 考虑当前较矮的边(设为左边 left)。它与右边任何位置组合,面积都不会超过当前值——因为宽度只会更小、而短板高度最多还是它自己。既然以 left 为短板的所有组合里当前这个已是最大,left 就可以被安全地“淘汰”,指针右移。这样每淘汰一条边就前进一步,最终两指针相遇,全程 。
下面的交互动画完整演示对样例 [1, 8, 6, 2, 5, 4, 8, 3, 7] 的双指针收缩过程:蓝色水面实时反映当前容量,可单步、自动播放与重置:
双指针 · 盛最多水的容器演示
样例输入:
[1, 8, 6, 2, 5, 4, 8, 3, 7]L0
1
2
3
4
5
6
7
R8
left0
right8
当前面积0
最大容量0
初始化:left 指向最左、right 指向最右,宽度最大。面积 = 两指针间宽度 × 较矮的那根柱子高度。
步骤 0 / 17
完整代码
js
/**
* 盛最多水的容器(双指针)
* @param {number[]} height 各线段高度
* @return {number} 最大容水量
*/
function maxArea(height) {
let left = 0 // 左指针,起于最左
let right = height.length - 1 // 右指针,起于最右
let best = 0
while (left < right) {
// 面积 = 较矮的边 × 当前宽度
const area = Math.min(height[left], height[right]) * (right - left)
best = Math.max(best, area)
// 移动较矮的一侧,才有机会让短板变高
if (height[left] < height[right]) {
left++
} else {
right--
}
}
return best
}复杂度分析
设 为数组长度。
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 暴力枚举 | 两两组合, 较大时超时 | ||
| 双指针 | 两指针共向内移动 步,一次遍历 |
双指针每次至少让
left或right前进一格,两者相遇即结束,总移动步数为 ,故时间 ,且只用了常数额外空间。
边界与易错点
易错点
- 面积取的是较矮的边:
min(height[left], height[right]),不是较高的,也不是两者之和。 - 移动方向不能反:必须移动较矮的一侧。移动较高一侧宽度变小、短板不升,面积必不增,会得到错误答案。
- 相等时移哪边都行:
height[left] === height[right]时,移动任意一侧都不会漏掉更优解(此时无论保留哪边,另一条边为短板的所有组合都不会更大)。 - 循环条件是
left < right:写成<=会让同一根线段与自身组合,宽度为 0。 - 元素个数少于 2:无法构成容器,结果为
0(while循环自然不执行,返回初始best = 0)。 - 别和「接雨水」混淆:本题只用两条边围水、取较矮边;接雨水是每个位置由左右两侧最高墙共同决定,二者模型不同。
一句话总结
宽度从最大开始只减不增,所以盯着短板走:每一步移动较矮的一侧,一次遍历 即可求出最大容量。