leetcode42.接雨水(困难)

leetcode42.接雨水(困难)_第1张图片
leetcode42.接雨水(困难)_第2张图片
做法1:动态规划来求左边和右边最大值

class Solution {
public:
    int trap(vector<int>& height) {
        //雨水能达到的最大高度为:左边最大值和右边最大值的最小值的高度
        int n = height.size();
        vector<int> left_max(n);
        vector<int> right_max(n);
        left_max[0] = 0;
        for (int i = 1; i < n; ++i) {
            left_max[i] = max(left_max[i - 1], height[i - 1]);
        }
        right_max[n - 1] = 0;
        for (int i = n - 2; i >= 0; --i) {
            right_max[i] = max(right_max[i + 1], height[i + 1]);
        }
        long long ans = 0;
        for (int i = 1; i < n; ++i) {
            if (min(left_max[i], right_max[i]) > height[i]) {
                ans += (min(left_max[i], right_max[i]) - height[i]);
            }
        }
        return ans;
    } 
};

做法2:单调栈
leetcode42.接雨水(困难)_第3张图片

class Solution {
public:
    int trap(vector<int>& height) {
        //维护一个单调递减的栈,如果小于等于栈顶入栈,
        //如果大于栈顶,则不断出栈一个元素 :
        //  如果栈不为空:宽度×高度就是当前层加的高度,ans+=
        //  如果栈为空,将该元素入栈
        int ans = 0;
        int n = height.size();
        vector<int> stk(n);
        int top = -1;
        for (int i = 0; i < n; ++i) {
            while (top != -1 && height[i] > height[stk[top]]) {
                int tmp = stk[top];
                --top;
                if (top != -1) {
                    int _min = min(height[i], height[stk[top]]);
                    ans += (i - stk[top] - 1) * (_min - height[tmp]);
                }
            }
            stk[++top] = i;
        }
        return ans;
    }
};

难点:
int _min = min(height[i], height[stk[top]]);
ans += (i - stk[top] - 1) * (_min - height[tmp]);
由于是一个单调递减的栈,所以雨水是一层一层的计算到的。

你可能感兴趣的:(#,栈&单调栈,接雨水)