参考资料:
LeetCode中的一篇博客:https://learnku.com/articles/50656
代码格式从 “华科不平凡” 的关于《直方图中的最大矩形》的解题博客中借鉴得来:https://blog.nowcoder.net/n/3414a193e9004d7cb93137fadece000c
结合参考资料进行题目分析
了解参考资料可以知道,解决收集雨水问题如果要用到栈的知识的话,就是维护一个递减栈。也可以结合“华科不平凡” 的关于《直方图中的最大矩形》的解题博客来看,那道题是通过维护递增栈来解决问题。
分析示例给出的高程图可以得出以下结论,能够存水的位置是两边均高于中间的V字形。而通过维护一个递减栈能够找出符合要求的位置并计算存水量。重点理解18到25行,最好能够用不同的例子手动模拟栈来了解整个过程。
class Solution { public: /** * * @param A int整型一维数组 * @param n int A数组长度 * @return int整型 */ int trap(int* A, int n) { // 由于积水代表找到水坑(低于两边柱值的柱),维护一个减序栈能够实现 可以用 [2,1,0,2] 来手动验证 stack<int> stk; //维护一个减序栈,记录下A中的下标 int sum = 0; for(int i=0; i<n; ++i){ while(!stk.empty() && A[i] >= A[stk.top()]){ //若遇到违反严格递减序的元素 int water_pool_pos = stk.top(); stk.pop(); //water_pool_pos位置表示的元素小于i位置表示的元素 //若取得water_pool_pos后栈stk非空,则water_pool同时小于stk.top()位置的高,因此可以存水 //而若stk此时为空,则意味着water_pool_pos表示的位置比目前(从0到i-1)的柱都大 if(!stk.empty()){ //从i到stk.top之间的位置可以存水 int left_pos = stk.top(); int height = min(A[left_pos], A[i]) - A[water_pool_pos]; //计算存水高度 int width = i-left_pos-1; //计算存水宽度 sum += height * width; } else { break; //当前water_pool_pos不可能存水,具体原因见第17行注释 } } stk.push(i); } //此时栈中剩下的元素构成一个递减栈,存储不了水 return sum; } };