11. Container With Most Water

題意

給定n個非負整數a1,a2,...,ana_1,a_2,...,a_n,其中每個數表示座標點(i,ai)(i,a_i),i是數組下標,aia_i是對應高度.尋找兩條線,使得兩條線構成的長方形面積最大,盛水最多.

Example:

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

暴力破解

對每種情況進行循環,計算對應的面積,同時保存最大的面積.

class Solution {
public:
    int maxArea(vector<int>& height) {
        if (height.size()<2)
            return 0;
        int res = 0;
        for(int i=0;i<height.size();i++){
            for(int j=i+1;j<height.size();j++){
                int minH = min(height[i], height[j]);
                res = max(res, minH*(j-i));
            }
        }
        return res;
    }
};

時間複雜度O(N*N).時間複雜度太高.而複雜度太高主要是進行了一些實際上並不需要的計算,儘管利用對稱性,減少了一半的計算量.

雙指針

思路:面積等於底*高,底是由兩條線下標差決定,高是由兩條線最短的線決定(木桶理論).假如有兩個指針left和right分別指向頭和尾,此時的面積是min(a[left],a[right])(N1)min(a[left],a[right])*(N-1),而且這時候的底是最長的.如果這時候的面積值並不是最大值,也就是說存在:

BaseHeight&gt;min(a1,aN)(N1)Base * Height &gt; min(a_1,a_N) * (N-1).

這種情況下由於Base一定小於(N-1),也就是說Height要比之前的大,那麼,應該一定a1,aNa_1,a_N兩條線中較短的那條線,保證面積的高度可以發生改變(增大),也就是說:

  • 如果a1&lt;aNa_1 &lt; a_N,問題變成在a2,aNa_2,a_N之間查找最大面積,也就是left++;
  • 如果a1&gt;aNa_1 &gt; a_N,問題變成在a1,aN1a_1,a_{N-1}之間查找最大面積,也就是right–;
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left=0, right = height.size()-1;
        int area = 0;
        while(left < right){
            area = max(area, min(height[left], height[right])*(right-left));
            if(height[left] < height[right]) left++;
            else right--;
        }
        return area;
    }
};

時間複雜度O(N).

優化:關注自己解法存在的問題,優化方向是什麼.比如說暴力破解方法,N*N,主要是因爲做了一些不必要的計算,所以下一步的優化方向就是如何減少這些計算,這就需要重新審題,發現題目中的隱藏信息以及問題存在的性質.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章