盛水最多的容器
题目表述
给定一个数组height,长度为n,每个数代表坐标轴中的一个点的高度,height[i]是在第i点的高度,请问,从中选2个高度与x轴组成的容器最多能容纳多少水
1.你不能倾斜容器
2.当n小于2时,视为不能形成容器,请返回0
3.数据保证能容纳最多的水不会超过整形范围,即不会超过2^31-1
数据范围:
0<=height.length<=10^5
0<=height[i]<=10^4
示例
输入:
[1,7,3,2,4,5,8,2,7]
返回值:
49
思路
这种题目其实就是要求两个点(柱形)之间的最大矩形面积。那么首先想到的暴力求解法就是去算两两之间的矩形面积,这样的时间复杂度就为O(n^2)。那么此时可以对时间复杂度做进一步的优化。当像这种去寻求一个数组的子区间某方面特性的时候,可以考虑用双指针方法或者是动态规划来进行求解。那么在这里的话,用双指针则可以进行求解。
使用双指针i, j, 指向矩形的头尾借助木桶的短板效应原理,可以得知最终的矩形面积=底部(长)*高 =
(
j
−
i
)
∗
(
m
i
n
(
h
[
i
]
,
h
[
j
]
)
)
(j-i)*(min(h[i],h[j]))
(j−i)∗(min(h[i],h[j]))。那么每次移动时:
若短板向内移动时,矩形底部变短,但是短板的高度可能会增加,所以矩形的面积可能会增加;
若向内移动长板是,矩形底部变短,而短板的高度不可能大于此时短板的高度,因此矩形的面积一定会变小。
因此要想进一步得到最大面积的矩形,只能是通过向内移动短板去寻求最大的矩形面积;所以两个指针分别从两端出发,然后直至相遇结束。
代码
int maxArea(vector<int>& height) {
// write code here
int len = height.size();
if(len<2){
return 0;
}
int ans = 0;
int i = 0, j = len-1;
while(i<j){
int area = min(height[i], height[j])*(j-i);
if(area>ans){
ans = area;
}
if(height[i]<height[j]){
i++;
}else{
j--;
}
}
return ans;
}