給定 n 個非負整數 a1, a2, ..., an,每個數代表坐標點 (i, ai)。繪製 n 條垂直線,線 i 的兩個端點分別為 (i, ai) 和 (i, 0)。找出其中兩條線,使其與 x 軸共同構成的容器能容納最多的水。容器不能傾斜。
遍歷所有線對組合,計算面積,記錄最大值。簡單但超時。
觀察:內層循環反向遍歷時,底 (j - i) 單調遞減。若當前高度 min(h[i], h[j]) ≤ 歷史最大高度,則面積必然 ≤ 歷史最大面積,可直接 break 進入下一輪外層循環。
核心洞察:面積受限於較短板。移動較長板,底減少且高不增(仍受限於短板),面積必減;只有移動較短板,才有機會獲得更高的板從而增加面積。
public int maxArea(int[] height) {
int left = 0, 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;
}
原文提供了一種介於暴力與雙指針之間的優化:
private static int[] method(int[] array) {
int[] result = new int[2];
int maxArea = 0;
for (int i = 0; i < array.length; i++) {
int maxHeight = 0;
// 反向遍歷:底 (j-i) 遞減
for (int j = array.length - 1; j > i; j--) {
int height = Math.min(array[i], array[j]);
// 剪枝:只有高度超過歷史最大高度,才有可能產生更大面積
if (height > maxHeight) {
maxHeight = height; // 先更新最大高度
if (height * (j - i) > maxArea) {
maxArea = height * (j - i);
result[0] = i;
result[1] = j;
}
}
}
}
return result;
}
maxHeight 初始化在內層循環外,每輪外層循環重置public static void main(String[] args) {
int[] height = {1,8,6,2,5,4,8,3,7};
System.out.println("雙指針結果: " + maxArea(height)); // 49
System.out.println("剪枝版結果: " + Arrays.toString(method(height))); // [1, 8] 索引對應值 8 和 7
}

盛水最多容器問題展示了數學洞察力如何將 O(n²) 優化為 O(n)。雙指針法利用「短板效應」與「單調性」實現極致優化,是雙指針技巧的經典入門題。面試中建議直接給出雙指針解法,並能解釋移動策略的數學證明。