Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
题意还是好理解的,说白了就是木桶效应,只是变成了多个桶
盛水量多少,取决于那块最短的板
为了更好理解,引用leetcode某位大佬的图:
我们必须去用以两个垂直线中较短那条线为高,以两垂直线距离为长来算出最大面积
首先从暴力求解入手,
代码如下:
class Solution {
public:
int maxArea(vector<int>& height) {
int maxArea = 0;
int area = 0;
for (int left = 0; left < height.size(); ++left)
{
for (int right = left + 1; right < height.size(); ++right)
{
area = min(height[left], height[right]) * (right - left);
if (area > maxArea)
maxArea = area;
}
}
return maxArea;
}
};
毕竟是medium难度,怎么可能这么简单,结果当然是超时
Time Limit Exceeded
那么应该怎么办?怎么把时间复杂度降为O(n)?
既然这个木板短了,我们换个长的不就行了吗。我们可以用两个指针,一个指针left指向开始,另一个right指向结尾,如果left木板比right木板矮,那就让left指针右移;如果left木板比right木板高,那么right指针左移。为什么不是left木板比right木板高就右移left呢?因为木桶效应,盛水量多少,取决于那块最短的板。我们如果移动高的那块板没有任何用处,装水量还是跟原来那块短板相关!
代码如下:
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0;
int right = height.size() - 1;
int maxArea = 0;
while (left < right)
{
maxArea = max(maxArea, min(height[left], height[right]) * (right - left));
if (height[left] < height[right])
++left;
else
--right;
}
return maxArea;
}
};