1. 題目
2. 題意
題目的意思是一個數組,數組的每個值代表一個柱子的高度,求所有柱子兩兩組合中,兩個柱子跟x軸組成的區域最大容納水的量。轉換爲數學關係就是所有垂直x軸的線段兩兩組合,每個組合的值爲兩個線段之間的距離與兩條線段中較短線段的乘積。
3. 思路
最容易的思路就是,將所有的情況進行遍歷,即循環遍歷每種情況,暴力法求解,時間複雜度爲O(n²)。然後我們考慮如何降低時間複雜度,我們可以考慮,從柱子的最外面兩側的柱子,向中間進行靠攏,對於外側的柱子,他們已經取得了更大的兩線段之間的距離,爲了獲取更大的面積,向內移動的過程中,需要不斷更換組合中矮的柱子,纔有可能獲得更大的面積。
思路總結:通過設置兩個“指針”,從最外面兩側的柱子向中間進行靠攏,每次移動的柱子爲高度低的柱子,每次移動一格,移動後計算當前獲取的面積跟當前最大面積值,若大於當前最大面積值而覆蓋,之後再比較兩個柱子的高度,重複比較-移動-計算的過程,直到兩個柱子相遇。總體時間複雜度爲O(n)。
4. 解題代碼
暴力法:
public int maxArea(int[] height) {
int maxArea = 0;
// 遍歷所有情況進行比較求解
for (int i = 0; i < height.length; i++) {
for (int j = i + 1; j < height.length; j++) {
int temp = (j - i) * minHeight(height[i], height[j]);
if (maxArea < temp) {
maxArea = temp;
}
}
}
return maxArea;
}
private int minHeight(int a, int b) {
return a > b ? b : a;
}
從兩側向中間移動的方法:
public int maxArea(int[] height) {
int maxArea = 0, start = 0, end = height.length - 1;
// 直到兩個柱子相遇結束
while (start < end) {
// 判斷當前組合是否取得更大面積
int temp = (end - start) * minHeight(height[start], height[end]);
if (temp > maxArea) {
maxArea = temp;
}
// 判斷應該移動的柱子
if (height[start] < height[end]) {
start++;
} else {
end--;
}
}
return maxArea;
}
private int minHeight(int a, int b) {
return a > b ? b : a;
}