LeetCode 11「盛最多水的容器」的 Java 实现如下:
核心思路:双指针法
容器的盛水量由两个因素决定:宽度(两线距离)和高度(较短的那条线)。
关键洞察:每次移动较短的板。因为移动较长的板,宽度减小而高度受限于短板,容积只会变小或不变;只有移动短板,才有可能遇到更高的板来提升容积。
Java 代码实现
class Solution {
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int maxArea = 0;
while (left < right) {
// 当前容器的盛水量 = 宽度 × 较短边高度
int currentArea = Math.min(height[left], height[right]) * (right - left);
maxArea = Math.max(maxArea, currentArea);
// 移动较短的板
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return maxArea;
}
}
运行示例
以 height = [1,8,6,2,5,4,8,3,7] 为例:
步骤 left right 短板高度 宽度 面积 最大面积 移动方向
1 0 8 1 8 8 8 left++
2 1 8 7 7 49 49 right--
3 1 7 3 6 18 49 right--
... ... ... ... ... ... 49 ...
最终返回 49(由索引 1 和 8 的两条线构成)。
复杂度分析
项目 复杂度 说明
时间 O(n) 每个元素最多被访问一次
空间 O(1) 仅使用常数级变量
为什么移动短板是正确的?
这是本题的核心难点,可以用反证法理解:
假设当前 height[left] < height[right],如果我们不移动 left 而是移动 right,那么:
- 宽度一定减小(right - left 变小)
- 高度最多只能是 height[left](短板不变)
- 所以容积一定 ≤ 当前容积,不可能更优
因此,left 和 right 之间所有以 left 为左边界、以 right 左侧某位置为右边界的组合,都不可能超过当前值,可以安全地跳过,直接 left++。
这道题和「接雨水(LC 42)」是经典的双指针配对题,需要我帮你把接雨水也整理一下吗?