给定
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提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
ans1.
按列遍历,计算当前列可能存的雨水
计算当前列左边最高列,以及右边最高列。
两次最高列中低的决定水位,水位若高于当前列,则高出来的就是当前列能存的水
O(n^2) O(1)
小剪枝了一下
class Solution {
public:
int trap(vector<int>& height) {
int cnt = 0;
int length = height.size();
int maxleft = 0;
for(int idx = 1; idx < length-1; ++idx)
{
int maxright = 0;
//for(int leftidx = 0; leftidx < idx; ++ leftidx)
//{
// if(height[leftidx] > maxleft) maxleft = height[leftidx];
//}
if(height[idx-1] > maxleft) maxleft = height[idx - 1];
for(int rightidx = length-1; rightidx > idx; --rightidx)
{
if(height[rightidx] > maxright) maxright = height[rightidx];
}
int max = 0;
if(maxleft > maxright) max = maxright;
else max = maxleft;
int cur = max - height[idx];
if(cur > 0) cnt += cur;
}
return cnt;
}
};
ans2.
动态规划思想
空间换时间,花O(n)时间遍历一遍数组,得到一个数组maxi,maxi中下标为idx的元素,
记录idx列之前的最高柱子。同理,得到另一个数组,记录右侧最高。
此时,时间复杂度和空间复杂度都是O(n),之后再遍历一次即可。
注意:因为我的maxleft/maxright是idx左/右的最大值(不包括idx自己)
height[idx - 1]
height[idx + 1]
class Solution {
public:
int trap(vector<int>& height) {
int length = height.size();
int maxLeft[length];
maxLeft[0] = 0;
for(int idx = 1; idx < length; ++idx)
{
if(height[idx - 1] > maxLeft[idx - 1])
{
maxLeft[idx] = height[idx - 1];
} else{
maxLeft[idx] = maxLeft[idx - 1];
}
}
int maxRight[length];
maxRight[length-1] = 0;
for(int idx = length-2; idx >= 0; --idx)
{
if(height[idx + 1] > maxRight[idx + 1])
{
maxRight[idx] = height[idx + 1];
} else{
maxRight[idx] = maxRight[idx + 1];
}
}
int cnt = 0;
for(int idx = 1; idx <= length-2; ++idx)
{
int min = 100001;
if(maxLeft[idx] > maxRight[idx]) min = maxRight[idx];
else min = maxLeft[idx];
if(min > height[idx]) cnt = cnt + min - height[idx];
}
return cnt;
}
};
/
//简化一下
class Solution {
public:
int trap(vector<int>& height) {
int length = height.size();
int maxLeft[length];
maxLeft[0] = 0;
for(int idx = 1; idx < length; ++idx)
maxLeft[idx] = std::max(height[idx - 1],maxLeft[idx - 1]);
int maxRight[length];
maxRight[length-1] = 0;
for(int idx = length-2; idx >= 0; --idx)
maxRight[idx] = std::max(height[idx + 1], maxRight[idx + 1]);
int cnt = 0;
for(int idx = 1; idx <= length-2; ++idx)
{
int min = std::min(maxLeft[idx], maxRight[idx]);
if(min > height[idx]) cnt = cnt + min - height[idx];
}
return cnt;
}
};