来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
给定 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 * 10^4
0 <= height[i] <= 10^5
思路一:当前位置的积水量怎么求呢,当然是与左右两个位置有关系的,看5号位置,当前的储水量只与左边的最高和右边的最高有关(因为当前位置的水的高度,是由两边同时包起来才会被存储,往上数一格,只要能被包住那就可以存储水),同样四号位置,也是只与最左边最高即3号位和最右边最高即7号位有关。求法:min(左边最高,右边最高)-当前高度。
所以求法就是:从左到右扫一次,记录左边最高。从右向左扫一次,记录右边最高,就可以直接求最小值,减去当前的高度,累加起来即可。
class Solution {
public:
int i;
int ans;
int left[20005], right[20005];
int trap(vector<int>& height) {
left[0] = height[0];
for (i = 1; i < height.size(); i++){
left[i] = max(left[i - 1], height[i]);
}
for (i = height.size() - 1; i >= 0; i--)
{
right[i] = max(right[i + 1], height[i]);
}
for (i = 0; i < height.size(); i++){
ans += min(left[i], right[i]) - height[i];
}
return ans;
}
};
思路二:
和思路一不同的是,上面是一次性求出结果。即把当前最高能存储水的高度直接求出,而思路二就是只求局部的。因为当前的位置如果能存储水,那么两边一定有比它高的。还是上面的图,看位置5,他两边是高度1,那么当前就能得到高度为1的储水量,而4、5、6此时就是平行的(高度为1)。此时他们的储水量就可以用(7-3-1)–>(长度)*(两边高度的最小(3)-当前的高度(1))得出。用栈来模拟这个过程,如果当前的高度小于栈顶的高度直接入栈。反之,此时的栈顶元素就是两个都比他高的块夹住的。就可以求一下局部的储水量(上面的求法),弹出栈顶元素(因为求完局部,此时的栈顶元素就没有了意义(因为已经把空缺的部分的水算了出来)–>就像5位置)。然后把当前的元素入栈。一直到最后一个元素。
class Solution {
public:
int ans, now, top, ans1, ans2, ans3;
stack<int> a;
int trap(vector<int>& height) {
while (now < height.size()){
while (!a.empty() && height[now] > height[a.top()]){
ans3 = a.top();
a.pop();
if (a.empty()) break;
ans1 = now - a.top() - 1;
ans2 = min(height[now], height[a.top()]) - height[ans3];
ans += ans2 * ans1;
}
a.push(now);
now++;
}
return ans;
}
};