Leetcode:Question11--Container With Most Water
题目描述
解答步骤
这一题刚拿到手,首先想到的是使用两层循环,第一层从左到右遍历作为左柱子,第二层从右往左遍历作为右柱子,记录下最大的容水量并输出即可。这种方法的复杂度将大于O(n^2),不采用
(以下描述中左右柱子指代选定container的左右边界,数组下标从0开始)
接着发现可以添加一些限制条件来减少循环的次数。
- 首先,在左柱子选定(依次从左到右遍历)的情况下,假若左柱子的高度低于最右边柱子(size-1),那么没有必要进行循环,以该左柱子为左边界的最大桶必然以size -1 号柱子作为右边界
- 假如左柱子高度大于最右边柱子(size - 1),那么则有必要从右向左遍历,找到高度大于右柱子的柱子,计算它与左柱子共同构成的容器的大小是否大于目前最大值,假如大于,则替换
- 当新寻找的右柱子高度大于左柱子时,停止遍历
代码
class Solution {
public:
int maxArea(vector<int>& height) {
size = height.size();
max = height;
for (int i = 0; i < size - 1; ++i)
{
max[i] = (height[i] > height[size - 1] ? height[size - 1] : height[i]) * (size - 1 - i);
if (height[i] > height[size - 1]) {
int maxRight = size - 1;
for (int j = size - 1; j > i; --j)
{
if (height[j] > height[maxRight]) {
int temp = (j - i) * (height[i] > height[j] ? height[j] : height[i]);
if (temp > max[i]) {
max[i] = temp;
maxRight = j;
}
}
if ( height[i] <= height[maxRight] ) {
break;
}
}
}
}
result = max[0];
for (int i = 0; i < size - 1; ++i) {
if(max[i] > result){
result = max[i];
}
}
return result;
}
private:
std::vector<int> max;
int size;
int result;
};
此种方法通过设置限制条件减少了循环的数量,复杂度小于n ^ 2
进一步优化
上面的代码是选定左柱子,进而通过限制条件判定右柱子。但我们可以同时将条件放在左右柱子上。
- 假如左柱子高度高于右柱子,那么右柱子应该向左移动。因为左柱子假如向左移动,那么容器的容量只可能减小或不变
- 假如左柱子高度低于右柱子,那么左柱子应该向右移动。
代码如下
class Solution {
public:
int maxArea(vector<int>& height) {
if (height.size() == 0)
return 0;
int l = 0, r = height.size()-1;
int area = 0;
while (l < r){
int cur = min(height[l], height[r]) * (r - l);
area = max(area, cur);
if (height[l] <= height[r])
l++;
else
r--;
}
return area;
}
};