当青训营遇上码上掘金【攒青豆】==【接雨水】
题目信息
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
样例数据
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
解题思路
第一次看见这道题是在力扣上,就是传说中字节面试题【接雨水】
一个思路就是单调栈,以题目中数据为例,来说明一下这个过程。
设栈st初始为空,然后从左到右遍历height中的数据。
设当前正在遍历的数据的下标为cur,如果st为空或者height[cur] < height[st.top()]时,这个时候让cur入栈。
如果height[i] > height[st.top()],那么就从st中弹出一个元素,这个时候如果栈里面还有元素,
那么这个元素,
刚才弹出的元素,
当前遍历的元素
就刚好组成了一个凹,然后计算这个凹可以攒多少青豆。计算公式为:
高*宽=(( min(height[i], height[st.top()]) - height[t] )*(i - st.top() - 1);
然后循环这个过程,直到没有凹为止的时候。最后返回答案ans,一道美味的炒青豆就制作完成啦!
题解代码
class Solution {
public:
int trap(vector<int>& height) {
stack<int> st; // 单调递减栈
int n = height.size();
int ans = 0;
for(int i = 0; i < n; i++) {
// 栈非空 and 当前高度 大于 栈顶高度
while(!st.empty() and height[i] > height[st.top()]){
int t = st.top();
st.pop();
if(st.size())
ans += ( min(height[i], height[st.top()]) - height[t] )*(i - st.top() - 1);
}
st.push(i);
}
return ans;
}
};