題目地址:
https://www.lintcode.com/problem/container-with-most-water/description
給定一個數組,代表擋板的高度,選定兩個擋板,兩個擋板中間的區域可以看成一個水的盛具,其容積等於較矮的擋板的高度乘以寬度。要求返回最大容積。
思路是對撞雙指針,同時更新得到的容積。每次移動指針的時候,都選擇能產生更優解的方式。例如,兩個指針分別是和,當的時候,這個時候左移並不會得到更好的解(因爲盛具高度沒變,但底變窄了),所以此時右移;同理,當的時候要左移;而當的時候則需要同時移動兩個指針。代碼如下:
public class Solution {
/**
* @param heights: a vector of integers
* @return: an integer
*/
public int maxArea(int[] heights) {
// write your code here
if (heights == null || heights.length == 0) {
return 0;
}
int res = 0;
int l = 0, r = heights.length - 1;
while (l < r) {
res = Math.max(res, (r - l) * Math.min(heights[l], heights[r]));
if (heights[l] > heights[r]) {
r--;
} else if (heights[l] < heights[r]) {
l++;
} else {
l++;
r--;
}
}
return res;
}
}
時間複雜度,空間。
算法正確性證明:
數學歸納法。當數組長度爲時顯然成立。當數組長度爲的時候,由於當的時候,左擋板是的情況下的所有解都不可能超過,而已經更新在res
裏了,所以不需要枚舉左擋板是的情況了,將右移一位後,就得到了相同的但規模更小的問題,由歸納假設,算法可以得到正確答案,再和比較一下即得到全局最優解。其他情況類似。
證明的本質是,將全局問題分爲兩類,即以爲左擋板和不以爲左擋板的兩類,然後分別的最優解合起來的更優解即爲全局最優解。