LeetCode(11):盛最多水的容器


Medium!

題目描述:

給定 n 個非負整數 a1a2,...,an,每個數代表坐標中的一個點 (iai) 。畫 n 條垂直線,使得垂直線 i 的兩個端點分別為 (iai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。

注意:你不能傾斜容器,n 至少是2。

解題思路:

我們需要定義i和j兩個指針分別指向數組的左右兩端,然后兩個指針向中間搜索,每移動一次算一個值和結果比較取較大的,容器裝水量的算法是找出左右兩個邊緣中較小的那個乘以兩邊緣的距離,代碼如下:

C++參考答案一:

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int res = 0, i = 0, j = height.size() - 1;
 5         while (i < j) {
 6             res = max(res, min(height[i], height[j]) * (j - i));
 7             height[i] < height[j] ? ++i : --j;
 8         }
 9         return res;
10     }
11 };

下面這種方法是對上面的方法進行了小幅度的優化,對於相同的高度們直接移動i和j就行了,不再進行容量計算了,參見代碼如下:

C++參考答案二:

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int res = 0, i = 0, j = height.size() - 1;
 5         while (i < j) {
 6             int h = min(height[i], height[j]);
 7             res = max(res, h * (j - i));
 8             while (i < j && h == height[i]) ++i;
 9             while (i < j && h == height[j]) --j;
10         }
11         return res;
12     }
13 };

使用貪心算法 
 1.首先假設我們找到能取最大容積的縱線為 i, j (假定i < j),那么得到的最大容積 C = min( ai , aj ) * ( j- i) ; 
    2.下面我們看這么一條性質: 
  ①: 在 j 的右端沒有一條線會比它高!假設存在 k |( j < k && ak > aj) ,那么 由 ak > aj,所以 min(ai, aj, ak) =min(ai, aj) ,所以由i, k構成的容器的容積C’ = min(ai, aj) * (k - i) > C,與C是最值矛盾,所以得證j的后邊不會有比它還高的線; 
  ②:同理,在i的左邊也不會有比它高的線;這說明什么呢?如果我們目前得到的候選: 設為 x, y兩條線(x< y),那么能夠得到比它更大容積的新的兩條邊必然在[x, y]區間內並且 ax’ >= ax , ay’ >= ay; 
    3.所以我們從兩頭向中間靠攏,同時更新候選值;在收縮區間的時候優先從x, y中較小的邊開始收縮;

C++參考答案三:

 1 class Solution {  
 2 public:  
 3     int maxArea(vector<int>& height) {  
 4         int n=height.size();  
 5         int i=0,j=n-1;  
 6         int max=0;  
 7         while(i!=j){  
 8             if(height[i]<height[j]){  
 9                 int valid_height=height[i];  
10                 int temp_area=valid_height*(j-i);  
11                 max=max>temp_area?max:temp_area;  
12                 i++;  
13             }  
14             else{  
15                 int valid_height=height[j];  
16                 int temp_area=valid_height*(j-i);  
17                 max=max>temp_area?max:temp_area;  
18                 j--;  
19             }  
20               
21         }  
22         return max;  
23     }  
24 };  

C++參考答案四:

逼近法 
每次左右兩端都舍去短的那一端 
若選擇短的那一端【S=小於等於此端的高*小於等於當前的最大區間長度】,至多的面積也是選擇最左最右的一個矩形,因此不必再考慮短的一端,直接舍去逼近

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4     int _m = 0, r = height.size()-1,l=0;
 5     while (r > l) {
 6         _m = max(_m, min(height[l], height[r])*(r - l));
 7         if (height[r] > height[l]) ++l;
 8         else --r;
 9     }
10     return _m;
11     }
12 };

通過設置兩個指針,分別指向數組的頭和尾,計算容器可以容納多少水,然后比較頭指針和尾指針對應的高度,矮的那個前進或后退一步(很好理解)。

python參考答案五:

 1 class Solution:
 2     def maxArea(self, height):
 3         """
 4         :type height: List[int]
 5         :rtype: int
 6         """
 7         l = 0
 8         r = len(height) - 1
 9         contain = 0
10         while l < r:
11             contain = max(contain, (r - l) * min(height[l], height[r]))
12             if height[l] > height[r]:
13                 r -= 1
14             else:
15                 l += 1
16 
17         return contain

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM