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.
给定n个非负整数a1,a2,…,an,其中每个表示坐标(i,ai)处的点。n画垂直线,使线i的两个端点位于(i,ai)和(i,0)。找到两条线,这两条线与x轴一起构成一个容器,这样容器中的水最多。
Note: You may not slant the container and n is at least 2.’
备注:你不能倾泻容器,而且n至少为2
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
上述垂直线由数组[1,8,6,2,5,4,8,3,7]表示。在这种情况下,容器可容纳的最大水面积(蓝色部分)为49。
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
思路:
一开始就想到直接暴力搜索,遍历2遍数组,穷举所有情况,储存最大值maxarea,结果当然超时。
我突然想到一个O(n2)的算法.jpg
超时代码( O(n2) BF暴力搜索)
class Solution {
public:
int maxArea(vector<int>& height) {
int maxarea = 0;
for (int i = 0; i < height.size(); i++)
for (int j = i + 1; j < height.size(); j++)
maxarea = max(maxarea, min(height[i], height[j]) * (j - i));
return maxarea;
}
};
方法改良:使用Two pointer (指针对撞?),利用问题本身与序列的特性,使用两个下标 i、j 对序列进行扫描。
每次只移动更小的那线,计算新的面积,直到2根线对撞为止。
AC代码( O(n) ,Two Pointers)
class Solution {
public:
int maxArea(vector<int>& height) {
int maxarea = 0,left = 0,right = height.size()-1;
while(left<right){
maxarea = max( maxarea, min( height[left],height[right]) *(right-left) );
if(height[left] <= height[right])
left++;
else
right--;
}
return maxarea;
}
};