1. 程式人生 > >【LeetCode】11. Container With Most Water(C++)

【LeetCode】11. Container With Most Water(C++)

題目:

Given n non-negative integers a1,a2,,ana_1, a_2, \dots, a_n, where each represents a point at coordinate (i,ai)(i, a_i). n vertical lines are drawn such that the two endpoints of line i is at (i,ai)(i, a_i) and (i,0)(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 1:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49

理解:

陣列的元素代表了高,由兩個邊構成一個容器,其高與短邊相同。要求最大的容積。
想到的方法是暴力搜,把所有的情況遍歷一遍,但是這樣需要O

(n2)O(n^2)複雜度。
注意到這樣的性質。對於一個已有的容器,其左邊和右邊的下標分別為i,ji,j

  • 若把其中的長邊向裡靠,得到的新容器的容積一定是小於現有的容積的。因為寬縮短了,新的邊如果小於原來的短邊,則高也會縮短;如果比原來的長邊長,高不變。總而言之,容積一定會變小。
  • 若把短邊往裡靠,容積可能是大於現在的。雖然寬縮短了,但是高有可能是增加的。

因此,藉助這個性質,使用兩個指標,分別從兩端開始計算容積,並收縮短邊即可。

實現:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int l=0,r=height.size()-1;
        int maxArea=0;
        while(l<r){
            maxArea=max(maxArea,min(height[l],height[r])*(r-l));
            if(height[l]<=height[r])
                ++l;
            else
                --r;       
        }
        return maxArea;
    }
};

看到一種實現,避免了收縮後的邊和現在的長度相同情況下重複計算面積。因為這種情況下,面積是不會增加的。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int l=0,r=height.size()-1;
        int maxArea=0;
        while(l<r){
            int h=min(height[l],height[r]);
            maxArea=max(maxArea,h*(r-l));
            while(l<r&&h==height[l]) ++l;
            while(l<r&&h==height[r]) --r;
        }
        return maxArea;
    }
};

不過跑的竟然比上一種慢。。神奇