题目连接
https://leetcode-cn.com/problems/container-with-most-water
题目详情
给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
题解
0、最简单的做法无疑就是暴力求解了,通过计算两两垂直线构成的容器的容量,选取容量最大那个即可,但是这样的时间复杂度是O(n^2),显然太高了。
1、更快的做法是设立首尾两个指针,分别指向数组的头部和尾部,然后向中间遍历,直到两个指针相遇,在每个位置,计算当前首尾指针所指向的垂直线构成的容器的容量,如果大于当前最大容量(最大容量的值初始化为首尾两根垂直线所构成容器的容量),即更新最大容量的值,然后舍弃两条垂直线中较短的那条,继续遍历到下一个位置,直到两个指针相遇。
2、为什么舍弃两条线中较短那条?
假设i,j是当首尾两个指针指向的位置,且height[i]<height[j],那么height[i]不可能与i+1到j-1之间的任何边组成容量更大的容器,因为height[i]不变时,减少j,那么容器的宽在不断降低,且容器的高不可能高于height[i],所以没有必要保留height[i]。
3、当首尾指针指向的边等高时呢?
其实一样,两条边都不可能与剩下的边组成容量更大的容器,所以任选一边舍弃或者直接舍弃两边。
代码
class Solution {
public:
int maxArea(vector<int>& height) {
if(height.size()<2)
return -1;
int max_cal,i,j;
i=0;j=height.size()-1;
max_cal=height[i]<height[j]?height[i]*(j-i):height[j]*(j-i);
while(i<j)
{
if(height[i]<height[j])
i++;
else
j--;
int cur=height[i]<height[j]?height[i]*(j-i):height[j]*(j-i);
if(cur>max_cal)
max_cal=cur;
}
return max_cal;
}
};