題目描述
首先記錄一下題目的解法。使用雙指標記錄容器的邊界,從邊界最大的容器開始,i
位於最左側,j
位於最右側。每次向中間移動高度較小的那個指標,並使用一個變數res
記錄容器最大的容積(即最終的答案)。
// C++
class Solution {
public:
int maxArea(vector<int>& height) {
int i = 0, j = height.size() - 1;
int res = 0;
while (i < j) {
int area = (j - i) * min(height[i], height[j]);
res = max(res, area);
if (height[i] < height[j]) {
i++;
} else {
j--;
}
}
return res;
}
};
// Java
class Solution {
public int maxArea(int[] height) {
int i = 0, j = height.length - 1;
int res = 0;
while (i < j) {
int area = j - i;
if (height[i] < height[j]) {
area *= height[i];
res = Math.max(res, area);
i++;
} else {
area *= height[j];
res = Math.max(res, area);
j--;
}
}
return res;
}
}
官方的題解中解釋了這種做法的正確性。我在這裡記錄一下我的直觀想法。對於這種題目,最粗暴的想法自然是使用雙重迴圈遍歷每一種邊界下標組合,記錄最大的那個答案,顯然對於較大的資料量來說,這種做法的時間複雜度為平方級,很容易超時。那麼我們該如何進行剪枝,跳過一些情況的判斷呢?將兩個指標放在最遠的兩端開始向中間靠攏,\(S=(j-i) \times min(h_i, h_j)\),當指標向中間移動時,第一個乘數項一定變小,要想讓整體的面積(容器的容積)變大,第二個乘數就只能變大,如果我們移動高度較大的那個指標(假設height[i] < height[j]
,我們移動j
),\(min(h_i,h_j)\)這一項仍然由高度較小(即i
和height[i]
)的那一項決定,也就是說移動高度較大的指標不會使這一項變大,當且僅當我們移動高度較小的那個指標時,才有可能使得此項變大。這也是為什麼我們每次移動其中一個指標的原因。