Description
Simulation
思路:
- 看图分析,只有下一个大于等于自己的元素插入才会形成凹槽接到雨水。所以显而易见,我们应该使用单调栈。
- 单调性怎么判断?很明显,比自己小的可以直接插入,大的插入要让前面的小元素出栈,因此我们需要一个递减的栈(栈顶元素最小)。
- 面积怎么计算?底 ✖ 高大伙都知道,然后按行计算,下面是分析:
首先明确一下单调栈里到底要存什么内容,每个柱的高度?不不不!我们需要下标来计算宽度,而下标又可以直接get到对应的高度,所以只需一个单调栈来存储下标就可以了。
画了一张图进行模拟计算过程,一组数[2,1,0,3]
从左到右依次入栈:
- 2入栈,栈为空,下标i直接入栈,栈内元素
i
。 - 1<2,直接入栈,栈内元素
i, i+1
。 - 0<1,直接入栈,栈内元素
i, i+1, i+2
。 - 3>0,保存0作为基底然后出栈,计算凹槽面积:高为1,选择3与当前栈顶元素1之间小的那个(木桶理论,看短的);底为1,3的下标减去1的下标
(i+3) - (i+2)
;总面积+1,继续判断 👇 - 3>1,保存1作为基底然后出栈,计算凹槽面积:高为1,因为1作为基底,此时栈顶元素为2,所以高为
2-1=1
,下标计算出底为2;总面积+2,继续判断 👇 - 3>2,2出栈,但此时栈为空,不需要继续计算。3终于入栈,最后栈内元素
i+3
。 - 总面积为3
看完模拟过程,相信你已经有了思路,单调减的栈,三板斧一整,我们只需要在出栈的时候计算面积即可。下面给出完整代码 🍉🍉🍉
Solution
// hrh 8/29
class Solution {
public:
int trap(vector<int>& h) {
stack<int> stk;
int res = 0;
// 三板斧!
for (int i = 0; i < h.size(); i++) {
while (!stk.empty() && h[i] >= h[stk.top()]) {
int base = h[stk.top()]; // 保存基底然后出栈
stk.pop();
// 栈不空时计算面积
if (!stk.empty()) {
int height = min(h[stk.top()], h[i]) - base;
int width = i - stk.top() - 1;
res += height*width;
}
}
stk.push(i);
}
return res;
}
};
Conclusion
再复习一下解题过程:
- 判断这道题能否用单调栈解决。
- 判断单调性,给出三板斧。
- 模拟计算过程,删改模板得到结果。
一道Hard题就轻松解决了~