接雨水

题目

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105

思路

能接雨水,必须是一个凹槽,两端大,中间小。计算每一个凹槽的接雨量,并汇总就是答案。柱子形成一个凹槽必然是先下降,后上升。遍历数组,用一个栈来记录从大到小的高度,大的在栈底,小的在栈顶。如果遇到比栈顶大的,则以当前位置为右侧,栈顶为底部,栈顶第二个元素为左侧形成一个凹槽。计算当前这个凹槽的面积。然后出栈,继续看以当前位置为右侧,栈顶为底部,栈顶第二个元素为左侧,是否能形成一个凹槽,如果能,则继续计算面积。

代码

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        int ans = 0;
        stack<int> indexStack;
        for(int i = 0;i < n;i++) {
            while (!indexStack.empty()&&height[indexStack.top()] < height[i]) {
                int top = indexStack.top();
                indexStack.pop();
                if (indexStack.empty()) {
                    break;
                }
                int secondTop = indexStack.top();
                int curWidth = i - secondTop - 1;
                int curHeight = min(height[i], height[secondTop]) - height[top];
                ans += curWidth*curHeight;
            }
            indexStack.push(i);
        }
        return ans;
    }
};