原作链接:
转自: 【接雨水】单调递减栈,简洁代码,动图模拟.
题目描述:
给定 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
- 0 <= n <= 3 * 104
- 0 <= height[i] <= 105
思路:
- 使用单调栈, 【单调栈入门】.
- 单调递减栈
2.1. 理解题目,参考图解,注意题目的性质,当后面的柱子高度比前面的低时,是无法接雨水的
2.2. 当找到一根比前面高的柱子,就可以计算接到的雨水
2.3. 所以使用单调递减栈 - 对更低的柱子入栈
3.1. 更低的柱子以为这后面如果能找到高柱子,这里就能接到雨水,所以入栈把它保存起来
3.2. 平地相当于高度 0 的柱子,没有什么特别影响 - 当出现高于栈顶的柱子时
4.1. 说明可以对前面的柱子结算了
4.2. 计算已经到手的雨水,然后出栈前面更低的柱子 - 计算雨水的时候需要注意的是
5.1. 雨水区域的右边r
指的自然是当前索引i
5.2. 底部是栈顶st.top()
,因为遇到了更高的右边,所以它即将出栈,使用cur
来记录它,并让它出栈
5.3. 左边l
就是新的栈顶st.top()
5.4. 雨水的区域全部确定了,水坑的高度就是左右两边更低的一边减去底部,宽度是在左右中间
5.5 使用乘法即可计算面积
动图解
题解:
单调递减栈
@Override
class Solution {
public:
int trap(vector<int>& height)
{
int ans = 0;
stack<int> st;
for (int i = 0; i < height.size(); i++)
{
while (!st.empty() && height[st.top()] < height[i])
{
int cur = st.top();
st.pop();
if (st.empty()) break;
int l = st.top();
int r = i;
int h = min(height[r], height[l]) - height[cur];
ans += (r - l - 1) * h;
}
st.push(i);
}
return ans;
}
};
/*
作者:ikaruga
链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/trapping-rain-water-by-ikaruga/
来源:力扣(LeetCode)
*/