leetcode-[數組、雙指針-對撞指針] - 乘最多水的容器(11)

1、問題描述

給定一個有n個非負整數的數組,以數組的索引作爲x座標,對應索引的元素值作爲y座標,找到兩個座標(x1,y1)和(x2,y2),使得他們與x軸圍成的矩形面積最大。
如下圖所示,圖中垂直線的高度代表輸入數組 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示爲藍色部分)的最大值爲 49。
在這裏插入圖片描述

2、解題思路

  • 邊界條件:(1)數組的元素個數小於等於2;
  • 問題分析:這道題和two-sum問題很像,two-sum問題是要求找到數組和等於某個值的兩個數,而這道題是要求找到兩個座標(索引及其對應的元素值),使得它們與x軸圍成的面積最大。所以可以採用雙指針來解決。在給出具體的雙指針移動規則前,我們先來看一下怎麼移動纔有可能使得面積增大。
  • 假設由h[i]h[i]h[j]h[j]以及xx軸圍成的矩形面積爲S(i,j)S(i,j)
  • S(i,j)=min(h[i],h[j])(ji)S(i,j)=min(h[i],h[j]) *(j-i);
  • 無論是ii還是jj往中間移動時,(ji)(j-i)都在變小,
  • 假設min(h[i],h[j])=h[i]min(h[i],h[j])=h[i],即兩者中最小的爲h[i]h[i],接下來,
  • 如果令ii向中間移動一位到i+1i+1
  • (1) 當h[i+1]>h[i]h[i+1]>h[i]時,min(h[i+1],h[j])min(h[i+1],h[j])變大,S(i+1,j)S(i+1,j)可能變大;
  • (2) 當h[i+1]=h[j]h[i+1]=h[j]時,min(h[i+1],h[j])min(h[i+1],h[j])不變,S(i+1,j)S(i+1,j)變小;
  • (3) 當h[i+1]<h[i]h[i+1]<h[i]時,min(h[i+1],h[j])min(h[i+1],h[j])變小,S(i+1,j)S(i+1,j)也變小;
  • 如果讓jj向中間移動一位到j1j-1
  • (1) 當h[j]>=h[j1]h[j]>=h[j-1]時,min(h[i],h[j1])min(h[i],h[j-1])要麼不變,要麼變小,S(i,j1)S(i,j-1)變小;
  • (3) 當h[j]<h[j1]h[j]<h[j-1]時,min(h[i],h[j1])min(h[i],h[j-1])不變,S(i,j1)S(i,j-1)也變小;
  • 以上分析可以看出,只有令h[i]h[i]h[j]h[j]中短板對應的索引向後移動,纔有可能使得h[i]h[i]h[j]h[j]中的短板變大,從而纔有可能獲得更高的面積S(i,j)S(i,j)
  • 雙指針移動規則:如果h[i]<h[j]h[i]<h[j],則讓ii向後移動一位,否則讓jj向前移動一位。直到i==ji==j停止。
  • 數據結構:
  • 雙指針i,j。i從數組頭部開始,j從數組尾部開始;
  • 記錄最大的矩形面積max_area,如果h[i],h[j]圍成的矩形面積大於max_area,則更新它;
  • 時間複雜度爲O(n)O(n),空間複雜度爲O(1)O(1)
i = 0;
j = h.length -1
max_area = min(h[i],h[j]) * (j-i)
while (i != j) Do{
	if (h[i] < h[j]){i+=1}
	else{j-=1}
	new_area = min(h[i],h[j]) * (j-i)
	if(new_area > max_area){ max_area = new_area}
}

3、代碼實現

class Solution {
public:
    int maxArea(vector<int>& height) {
        int length = height.size();
        if(length < 2){
            return 0;
        }
        int i = 0;
        int j = length - 1;
        int max_area = minh(height[i],height[j]) * (j-i);
        while(i != j){
            if(height[i] < height[j]){
                i ++;
            }
            else{
                j--;
            }
            int new_area = minh(height[i],height[j]) * (j - i);
            if(new_area > max_area){
                max_area = new_area;
            }
        }
        return max_area;  
    }
    int minh(int a, int b){
        int min_h = (a < b) ? a : b ;
        return min_h;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章