问题描述:
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
解题思路:
刚开始看到题目首先想到的就是暴力解法,很简单就可以实现,但是时间复杂度是O(n2),显然不符合一个中等题的难度,但我还是写了下来试了一下,果然超时了。超时代码:
class Solution {
public:
int maxArea(vector<int>& height) {
int max=0;
int shortline;
//遍历
for(int i=0;i<height.size();i++)
{
for(int j=i+1;j<height.size();j++)
{
//选短边
if(height[i]<=height[j])
{
shortline=height[i];
}
else
shortline=height[j];
int s=shortline*(j-i);
if(s>max)
max=s;
}
}
return max;
}
};
为了解决时间复杂度的问题,保证在O(n)的时间内能完成,可以有一个新思路:
设置两个指针,分别指向数组的头和尾,然后计算这两个指针所指位置区域的面积,这样计算的最大面积就是问题的解。那这两个指针该如何移动又成了新的问题。
指针移动思路:
1. 开始两个指针left指向数组头,right指向数组尾
2. 计算两个指针之间的面积,长为 right-left 宽为 min(a[right],a[left])
3. a[left] 和 a[right] 哪个小移动哪个,因为他是限制面积不是最大的原因!!
4. left 和 right 到达同一个位置时结束 ,把 max 返回
class Solution {
public:
int maxArea(vector<int>& height) {
int max=0;
int left=0;
int right=height.size()-1;
while(left<right)
{
int s=(right-left)*min(height[left],height[right]);
if(s>max)
max=s;
if(height[left]<=height[right])
left++;
else
right--;
}
return max;
}
};