[LeetCode] 11. 最も多くの水を入れる容器。難易度:中程度。
1. トピック
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
2. 私の解決策: ダブル for ループ、制限時間を超過する
最も簡単に考えられるのは暴力的なループで、二重の for ループはすべての状況を横断して最大値を取得します。時間計算量は O(n^2) で、制限時間を超えています。コード:
class Solution {
public:
int max(int a,int b){
return a>b?a:b;
}
int min(int a,int b){
return a<b?a:b;
}
int maxArea(vector<int>& height) {
int length=height.size();
int maxWater=0;
for(int i=0;i!=length-1;i++)
for(int j=i+1;j!=length;j++){
maxWater=max(maxWater,min(height[i],height[j])*(j-i));
}
return maxWater;
}
};
3. 最適な解決策: ダブル ポインターが両側から移動する
長方形の面積は、次の 2 つの要素に関係します。
(1) 長方形の長さ: 2 本の直線の間の距離
(2) 長方形の幅: 2 本の直線のうち短い方の長さ
したがって、長方形の面積を最大化するには、2 本の垂直線の間の距離をできるだけ長くし、2 本の垂直線の最短の長さをできるだけ長くする必要があります。
配列の左端と右端をそれぞれ指すように、左右の 2 つのポインターを設定します。このとき、2つの直線の間の距離が最も遠いので、次の長方形の面積が現在の面積より大きい場合は、高さ[左]と高さ[右]のうち短い方の直線を右に移動する必要があります。真ん中の長い直線が見つかるかどうかを確認します。
コード:
class Solution {
public:
int max(int a,int b){
return a>b?a:b;
}
int min(int a,int b){
return a<b?a:b;
}
int maxArea(vector<int>& height) {
const int length=height.size();
int left=0;
int right=length-1;
int maxWater=0;
while(left<right){
maxWater=max(maxWater,min(height[left],height[right])*(right-left));
if(height[left]<height[right])
left++;
else
right--;
}
return maxWater;
}
};