先上代码。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 class Solution { 7 public: 8 int maxArea(vector<int> &height) { 9 if (height.empty()) return 0; 10 int i = 0, j = height.size() - 1; 11 int max = INT_MIN; 12 int area; 13 while (i < j) 14 { 15 area = min(height[i],height[j])*(j-i); 16 if (area>max) max = area; 17 if (height[i] < height[j]) i++;//谁是短板,谁就该移动 18 else j--; 19 } 20 return max; 21 } 22 }; 23 24 int main() 25 { 26 Solution s; 27 int array[] = {2,5,3,1,6}; 28 vector<int> h(array,array+5); 29 cout << s.maxArea(h)<<endl; 30 return 0; 31 }
http://blog.unieagle.net/2012/09/16/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Acontainer-with-most-water/
最笨的方法是暴力破解,加上一点预判。时间是O(n^2)
看了nandawys的评论,找到了O(n)方法,思路是从两头到中间扫描,设i,j分别指向height数组的首尾。
那么当前的area是min(height[i],height[j]) * (j-i)。
当height[i] < height[j]的时候,我们把i往后移,否则把j往前移,直到两者相遇。
这个正确性如何证明呢?
代码里面的注释说得比较清楚了,即每一步操作都能保证当前位置能取得的最大面积已经记录过了,而最开始初始化的时候最大面积记录过,所以有点类似于数学归纳法,证明这个算法是正确的。
Container With Most Water
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.
代码
600ms过大集合
class Solution {
public:
int maxArea(vector<int> &height) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int max = 0;
for( int i = 0 ; i < height.size(); ++i)
{
int hi = height[i];
if(hi == 0)
continue;
int minPosibleIndex = max / hi + i;
for(int j = height.size() - 1; j > i && j >= minPosibleIndex; --j)
{
int hj = height[j];
int area = min(hi,hj) * (j - i);
if (area > max)
max = area;
}
}
return max;
}
};
Code rewrite at 2013-1-4,O(n)
1 class Solution { 2 public: 3 int maxArea(vector<int> &height) { 4 if (height.size() < 2) return 0; 5 int i = 0, j = height.size() - 1; 6 int maxarea = 0; 7 while(i < j) { 8 int area = 0; 9 if(height[i] < height[j]) { 10 area = height[i] * (j-i); 11 //Since i is lower than j, 12 //so there will be no jj < j that make the area from i,jj 13 //is greater than area from i,j 14 //so the maximum area that can benefit from i is already recorded. 15 //thus, we move i forward. 16 //因为i是短板,所以如果无论j往前移动到什么位置,都不可能产生比area更大的面积 17 //换句话所,i能形成的最大面积已经找到了,所以可以将i向前移。 18 ++i; 19 } else { 20 area = height[j] * (j-i); 21 //the same reason as above 22 //同理 23 --j; 24 } 25 if(maxarea < area) maxarea = area; 26 } 27 return maxarea; 28 } 29 };