给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5] 输出:9
思路:
height [ i ]位置能接的雨水 = min( height [ 0 .. i ]的最大值,height [ i .. n-1 ]的最大值 ) - height[ i ]
//备忘录:记录height[i]的左边最大值和右边最大值
class Solution {
public:
//height[i]位置能接的雨水=min(height[0..i]的最大值,height[i..n-1]的最大值)-height[i]
int trap(vector<int>& height) {
int n=height.size();
vector<int> leftMax(n,0);
vector<int> rightMax(n,0);
//base case
leftMax[0]=height[0];
rightMax[n-1]=height[n-1];
int res=0;
for(int i=1;i<n;i++)//从左往右求左边最大值
{
leftMax[i]=max(height[i],leftMax[i-1]);
}
for(int i=n-2;i>=0;i--)//从右往左求右边最大值
{
rightMax[i]=max(height[i],rightMax[i+1]);
}
for(int i=0;i<n;i++)
{
res+=min(leftMax[i],rightMax[i])-height[i];
}
return res;
}
};
因为使用备忘录,所以空间复杂度为O(N),下面的方法使用左右指针,时间复杂度不变,空间复杂度降至O(1)
左右指针———找到height[ 0 .. left ]的最大值和height[ right .. n-1 ]的最大值
如上图,l_max < r_max
,但是 r_max
并不是右边最大的,这是因为它是不是最大的不重要,重要的是 height[i]
能够装的水只与较低的l_max
有关。
//左右指针,找到height[0..left]的最大值和height[right..n-1]的最大值
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size();
int left=0;
int right=n-1;
int leftMax=0;
int rightMax=0;
int res=0;
while(left<right)
{
leftMax=max(leftMax,height[left]);
rightMax=max(rightMax,height[right]);
//res+=min(leftMax, rightMax)-height[i]
if(leftMax<rightMax)
{
res+=leftMax-height[left];
left++;
}
else
{
res+=rightMax-height[right];
right--;
}
}
return res;
}
};
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1] 输出:1
思路:
左右指针,当前状态能容纳的水 = min( height[ left ] , height[ right ] ) * ( right - left )
当height[ left ] < height[ right ]时,left ++;
当height[ right ] < height[ left ]时,right --;
都是移动高度更低的那条边,因为这条边移动后就有可能变高,使得容量增大。如果移动的是高度更高的那条边,它移动后变高,由于容器高度是受更短的那条边限制,所以容器高依然是那条短边,而宽变小,所以容量会变小;它移动后变低,那更是容量下降了。
class Solution {
public:
int maxArea(vector<int>& height) {
int n=height.size();
int left=0;
int right=n-1;
int res=0;
while(left<right)
{
int area=min(height[left],height[right])*(right-left);
res=max(res,area);
if(height[left]<height[right])
{
left++;
}
else
{
right--;
}
}
return res;
}
};