参考资料:

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;
    }
};