zoukankan      html  css  js  c++  java
  • [LeetCode 42] Trapping Rain Water

    Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.


    The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

    Example:

    Input: [0,1,0,2,1,0,1,3,2,1,2,1]
    Output: 6



    Monotonic Stack Solution, O(N) runtime and space
    To trap water, we just have higher bars on both side with lower bars in between. This means that when we see a height currH that is taller than a previous height prevH, we potentially just found
    the right boundary of the current trapping window. The base height where water get trapped is prevH. We then need to find the left boundary. This would be the most recent previous height that is
    taller than the base height. Any previous height that is shorter than this base height should have been accounted when the base height prevH was used as the right boundary. If we find such a left
    boundary, we add (Math.min(leftBoundary, rightBoundary) - baseHeight) * (rightBoundary - leftBoundary - 1) to the final count. If not, we know that so far we have only seen non decreasing heights,
    do nothing.

    To achieve, the above algorithm, we maintain a non-increasing monotonic stack of heights we processed so far. If the current height is non-increasing, we know that we have not seen a right boundary
    so far, push the current height into stack. Otherwise, if the current height is taller than the top of the stack, we need to find the left boundary then update the final cnt. Get all the heights from the top of
    the stack that have the same height, this is the base height. We acheive this by keep poping the stack top until its top is taller than the base height or the stack is empty.

    The stack is used to keep all possible left boundary of a certain water trapping window of certain base heights. Each time there is a potential right boundary, find its corresponding left boundary.

    class Solution {
        public int trap(int[] height) {
            Stack<Integer> stack = new Stack<>();
            int ans = 0;
            stack.push(0);
            int i = 1;
            while(i < height.length) {
                if(stack.size() == 0 || height[stack.peek()] >= height[i]) {
                    stack.push(i);
                }
                else {
                    while(stack.size() > 0 && height[stack.peek()] < height[i]) {
                        int currIdx = stack.pop();
                        int currHeight = height[currIdx];
                        while(stack.size() > 0 && height[stack.peek()] == currHeight) {
                            stack.pop();
                        }   
                        if(stack.size() > 0) {
                            int width = i - stack.peek() - 1;
                            ans += (Math.min(height[stack.peek()], height[i]) - currHeight) * width;
                        }
                    }
                    stack.push(i);                
                }
                 i++;
                
            }
            return ans;
        }
    }
    
    
    








  • 相关阅读:
    POJ 3660 Cow Contest 任意两点之间的关系 Floyd
    CDOJ 1146 A
    TTTTTTTTTTTTTT CDOJ Sliding Window 线段树(nlogn)或双端队列(n) 模板
    CDOJ 203 并查集+优先队列 好题
    CDOJ 1073 线段树 单点更新+区间查询 水题
    CDOJ 1070 秋实大哥打游戏 带权并查集
    CDOJ 1063 堆排序模板
    CDOJ 1069 秋实大哥去打工 单调栈 下标处理
    CDOJ 1061 C
    巨蟒python全栈开发django14:Form组件
  • 原文地址:https://www.cnblogs.com/lz87/p/7500099.html
Copyright © 2011-2022 走看看