法1:暴力枚举矩形的左右的两个端点,会TLE
class Solution {
public:
int maxArea(vector<int>& height) {
int res=0;
for(int i=0;i<height.size();i++)
{
for(int j=i+1;j<height.size();j++)
res=max(res,min(height[j],height[i])*(j-i));
}
return res;
}
};
法2:双指针扫描(思路来自力扣官方题解)
1.双指针的含义: 可以作为容器边界的所有位置的范围。在一开始,双指针指向数组的0,n-1,表示
数组中所有的位置都可以作为容器的边界,我们每次移动指针的时候,就表示我们认为
这个指针成为最大解的边界的可能了;
2.如何移动指针: 直觉上,假设左,右指针分别指向i,j,间距为t,每次无论移动哪个指针,t都会变为t-1,关键在h=min(h[i h[j]);
当h[i]<=h[j]时,移动i,否则移动j;就是谁小就移动谁;
3.正确性的证明:反正法:证明在h[i]<=h[j]的情况下,i不可能在最优解的左端点;
假设最优解为S,它的左端点为i,j*为右端点,向左移动j指向j*,由(j*-i)<(j-i),注意j此时还没到达右边界
min(h[i],h[j*])<=min(h[i],h[j]):
当h[j*]<=h[j]时,min(h[i],h[j*])<=h[i];
当h[j*]>h[j]时, min(h[i],h[j*])=h[i];
即无论我们怎么移动右指针,得到的容器的容量都小于移动前容器的容量,当j移动到右边界时的S小于移动之前的S&,与S时最优解矛盾
4.终止条件:i==j,即i,j之间t=0,答案就是每次在移动之前以目前可能的边界i,j算出S,每次移动都会出现新的边界
5.代码:
class Solution {
public:
int maxArea(vector<int>& height) {
int res=0;
int l=0,r=height.size()-1;
while(l<r)
{
res=max(res,min(height[l],height[r])*(r-l));
if(height[l]<=height[r]) l++;
else r--;
}
return res;
}
};
大晚上看到最后一张艾伦的图吓我一跳