Preface
上篇讲了每日温度,这篇来讲一道单调栈的Hard题 接雨水 - 力扣。
回忆一下上篇的解题步骤:
- 判断单调栈:一般来说,题目中要求找到一个元素左边(右边)第一个比自己大(小)的元素,我们应该首先想到单调栈。它的应用范围可以说是很窄,但缺点也是优点,这种题目类型很好辨认。
- 分析单调性: 分析时应该首先分析单调性,判断单调减还是单调增,直接给出三板斧(模板)。
- 计算: 在模板的基础上进行删改,计算题目要求。
照例贴出单调栈模板:
// 单调栈模板,不懂可以看我的上篇文章 for (遍历这个数组) { while (栈不为空 && 栈顶元素与当前数组元素比较) { 出栈; } 入栈; } 复制代码
42. 接雨水
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题就轻松解决了~