盛最多水的容器
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.length2 <= n <= 1050 <= 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
每次移动都排除了一根不可能再成为最优边界的柱子,所以总移动次数是 O(n)。
宽度 2 × 较矮高度 7 = 14;当前最大 24。
- 面积
- 14
- best
- 24
时间 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²),不能作为提交方案。
- 1i 从 0 到 n-1。
- 2j 从 i+1 到 n-1。
- 3用 min(height[i], height[j]) × (j-i) 更新 best。
易错点
- 内层 j 从 i 开始:会重复计算同一对柱子,还会把宽度 0 算进去。
- 用较大的高度算面积:容器会被较矮的一侧截断。
代码与演示
主解法配有图解;对照解法用于比较思路、复杂度或实现方式。
height = [2,7,3,8,4,6]left = 0,right = 5;先看最外侧两根柱子。
- left
- 0
- right
- 5
查看 C++ 代码
延伸阅读
- 双指针的合法性来自“排除不可能更优的边界”,不是随便移动;每一步都要能说清排除了什么。
- 同类题:接雨水(42)用左右最大值决定每列能接多少水,也是从两端向中间收。