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軸圍成的面積最大。所以可以採用雙指針來解決。在給出具體的雙指針移動規則前,我們先來看一下怎麼移動纔有可能使得面積增大。
- 假設由和以及軸圍成的矩形面積爲;
- ;
- 無論是還是往中間移動時,都在變小,
- 假設,即兩者中最小的爲,接下來,
- 如果令向中間移動一位到,
- (1) 當時,變大,可能變大;
- (2) 當時,不變,變小;
- (3) 當時,變小,也變小;
- 如果讓向中間移動一位到,
- (1) 當時,要麼不變,要麼變小,變小;
- (3) 當時,不變,也變小;
- 以上分析可以看出,只有令和中短板對應的索引向後移動,纔有可能使得和中的短板變大,從而纔有可能獲得更高的面積。
- 雙指針移動規則:如果,則讓向後移動一位,否則讓向前移動一位。直到停止。
- 數據結構:
- 雙指針i,j。i從數組頭部開始,j從數組尾部開始;
- 記錄最大的矩形面積max_area,如果h[i],h[j]圍成的矩形面積大於max_area,則更新它;
- 時間複雜度爲,空間複雜度爲。
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;
}
};