这是跟着代码随想录的顺序学习算法的第?天。
以下是学习时自己的一些理解与笔记,如有错误欢迎指正与讨论。
42.接雨水
参考相关链接:
笔记
单调栈解法
本题用单调栈解决的过程中有两个值得思考的点,一个是找到比栈顶元素更大的元素之后为什么可以算出雨水的面积,二是为什么遇到了相同元素之后只取最右边的元素。(边界??)
找到比栈顶元素更大的元素之后为什么可以算出雨水的面积?
这是因为此时利用了一个单调栈按照 height[i]
的大小来存储元素下标,从栈顶到栈底是递增的,这里暂时不讨论相同的高度,下一个问题中再对这种情况做处理,所以,不妨假设栈顶到栈底是严格递增的。(单调栈存的是下标,但这里比较的是 height
数组中的高度)
当遇到了一个比栈顶元素更大的元素的时候,这说明栈顶元素同时小于了栈中高度第二的元素和当前比较的元素,也就是形成了一个凹槽,所以就能够存储雨水。
计算思路就是用左右两边更低的边界高度(木桶效应嘛),来与栈顶元素高度作比较,得到雨水面积的高度,利用左右边界的距离来计算雨水面经的宽度。
算法具体实现的时候,又有两个值得一提的点。
第一个,是判断条件 if(st.length !== 0)
,这从语法上说是为了让栈中有元素可取,而不是取到 undefined
,从题目条件来说,就是考虑了左边界无法作为凹槽底部的情况;
第二个,是这里的循环判断,从单调栈的特点来说,这是为了让单调栈保持单调,栈顶元素必须大于 height[i]
,从题目的条件来说,就是第一次只将最靠近右边界的地方装了雨水使其达到了凹槽中的最高处,事实上,左边仍然可能存在可填充的凹槽没有被填充,也就是说,水往低处流嘛,除非这里存的是冰块(。
while (st.length !== 0 && height[i] > height[st[st.length - 1]]) {
// 注意这里是while
let mid = st[st.length - 1];
st.pop();<