【Leetcode】11. Container With Most Water (medium)
11. Container With Most Water (medium)
描述
Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note:You may not slant the container and n is at least 2.
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
Example:
Input: [1,8,6,2,5,4,8,3,7] Output: 49
分析
這道題目和 Trapping Rain Water
(收集雨水)有點類似。一開始拿到題目直接往那道題目上去套了,最後發現最後所求的結果只和邊界的高度有關。這道題目如果和收集雨水結合一下還是蠻麻煩的。
由於結果只和邊界的高度有關,只需要遍歷陣列,確定所有的可能由兩個邊界的組合即可。但是如果傻乎乎地寫了雙重遍歷:
for(int i = 0; i < height.length - 1; i++){ for(int j = i + 1; j < height.length; j++){ //do something } }
那麼無疑一個O(N^2)的時間複雜度是跑不掉了。當遇到雙重遍歷的時候,首先要考慮能不能使用夾逼法來取代雙重遍歷,這道題目就可以使用夾逼法來達到O(N)的時間複雜度。
使用兩個變數分別代表左右邊界,每次向中間移動左邊界或者右邊界,這樣只需要遍歷一次陣列。如何判斷是移動左邊界還是右邊界呢?最後的結果是左右邊界高度低的一方乘以二者之間的距離,二者之間的距離沒法改變,肯定是一直在減小的,那麼就要確保左右邊界高度較低的一方高度要高,那麼每次移動邊界的時候,移動高度較低的一方即可。
程式碼
public int maxArea(int[] height) { int i = 0, j = height.length - 1, sum = 0; while(i < j){ sum = Math.max(sum, Math.min(height[i], height[j]) * (j - i)); if(height[i] < height[j]){ i++; }else{ j--; } } return sum; }