Trapping Rain Water LT42

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. Thanks Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
1. 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.
Brute force: for each element/bar, find the left boundary and right boundary, the level of the water trapped on this bar is Min(leftBoundary, rightBoundary) - height[i].
start from the bar, scan to the left to get the leftBoundary, scan to the right to get the rightBoundary
Time complexity: O(n2)
Space complexity: O(1)
class Solution {
    public int trap(int[] height) {
       int area = 0;
       for(int i = 0; i < height.length; ++i) {
           int leftBoundary = height[i];
           for(int j = 0; j <i; ++j) {
               leftBoundary = Math.max(leftBoundary, height[j]);
           }
           int rightBoundary = height[i];
           for(int j = i+1; j < height.length; ++j) {
               rightBoundary = Math.max(rightBoundary, height[j]);
           }
           area += Math.min(leftBoundary, rightBoundary) - height[i];
       }
       return area;
    }
}
1.a It is observed that the leftBoundary and rightBoundary has been recomputed multiple times, with dynamic programing, we could compute them once and store the result in the array.
leftBoundary[i]: maximum height starting from left and ending at i, leftBoundary[i] = Math.max(leftBoundary[i-1], height[i])
rightBoundary[j]: maximum height starting from right and ending at j, rightBoundary[j] = Math.max(rightBoundary[j+1], height[j])
Time Complexity: O(n)
Space Complexity: O(n)
public class SolutionLT42 {
    private int findMaxHeight(int[] height) {
        int result = 0;
        for(int i = 0; i < height.length; ++i) {
            if(height[i] > height[result]) {
                result = i;
            }
        }
        return result;
    }
    public int trap(int[] height) {
        if(height == null || height.length <= 1) return 0;
        int highestBar = findMaxHeight(height);
        int area = 0;
        int leftBoundary = 0;
        for(int i = 0; i < highestBar; ++i) {
            leftBoundary = Math.max(leftBoundary, height[i]);
            area += leftBoundary - height[i];
        }
        int rightBoundary = 0;
        for(int i = height.length - 1; i > highestBar; --i) {
            rightBoundary = Math.max(rightBoundary, height[i]);
            area += rightBoundary - height[i];
        }
        return area;
    }
    public static void main(String[] args) {
        SolutionLT42 subject = new SolutionLT42();
        int[] testData = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
        System.out.println(subject.trap(testData));
    }
}
1.4a Instead of doing two passes, we can start from the two ends to find out the boundary on the go with only 1 pass
if leftBounday <= rightBoundary, ++left, if height[left] < leftBoundary, area = leftBoundary - height[left]; otherwise leftBoundary = height[left]
else ++right, if height[right] < rightBoundary, area = rightBoundary - height[right]; otherwise rightBoundary = height[right]
public class SolutionLT42 {
    public int trap(int[] height) {
        if(height == null || height.length <= 1) return 0;
        int area = 0;
        int leftBoundary = height[0];
        int rightBoundary = height[height.length - 1];
        for(int left = 0, right = height.length - 1; left < right;) {
            if(leftBoundary <= rightBoundary) {
                ++left;
                leftBoundary = Math.max(leftBoundary, height[left]);
                area += leftBoundary - height[left];
            }
            else {
                --right;
                rightBoundary = Math.max(rightBoundary, height[right]);
                area += rightBoundary - height[right];
            }
        }
        return area;
    }
    public static void main(String[] args) {
        SolutionLT42 subject = new SolutionLT42();
        int[] testData = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
        System.out.println(subject.trap(testData));
    }
}
2. Use stack, in order to store the boundary for a bar, we need to store the index of height in decreasing order of height, hence the previous element before the current would be the leftBoundary, if height[i] <= height[leftBoundaryStack.peek()], leftBoundaryStack.push(i); otherwise, the current element would be the rightBoundary.
public class SolutionLT42 {
    public int trap(int[] height) {
        if(height == null || height.length <= 1) return 0;
        int area = 0;
        Deque<Integer> leftBoundaryStack = new LinkedList<>();
        for(int i = 0; i < height.length; ++i) {
            while(!leftBoundaryStack.isEmpty() && height[leftBoundaryStack.peek()] < height[i]) {
                int rightBoundary = height[i];
                int current = leftBoundaryStack.pop();
                if(leftBoundaryStack.isEmpty()) {
                    break;
                }
                int leftBoundary = height[leftBoundaryStack.peek()];
                area += (Math.min(leftBoundary, rightBoundary) - height[current]) * (i - leftBoundaryStack.peek() - 1);
            }
            leftBoundaryStack.push(i);
        }
        return area;
    }
}
Refactoring the above code, replace while loop with if, especially the ++i, interesting...
public class SolutionLT42 {
    public int trap(int[] height) {
        if(height == null || height.length <= 1) return 0;
        int area = 0;
        Deque<Integer> leftBoundaryStack = new LinkedList<>();
        for(int i = 0; i < height.length;) {
            if(leftBoundaryStack.isEmpty() || height[leftBoundaryStack.peek()] > height[i]) {
                leftBoundaryStack.push(i);
                ++i;
            }
            else {
                int current = leftBoundaryStack.pop();
                if(leftBoundaryStack.isEmpty()) {
                    continue;
                }
                int rightBoundary = height[i];
                int leftBoundary = height[leftBoundaryStack.peek()];
                int distance = i - leftBoundaryStack.peek() - 1;
                int boundedHeight = Math.min(leftBoundary, rightBoundary) - height[current];
                area += distance * boundedHeight;
            }
        }
        return area;
    }
}
Trapping Rain Water LT42的更多相关文章
- [LeetCode] Trapping Rain Water II 收集雨水之二
		Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevati ... 
- [LeetCode] Trapping Rain Water 收集雨水
		Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ... 
- [LintCode] Trapping Rain Water 收集雨水
		Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ... 
- LeetCode:Container With Most Water,Trapping Rain Water
		Container With Most Water 题目链接 Given n non-negative integers a1, a2, ..., an, where each represents ... 
- LeetCode - 42. Trapping Rain Water
		42. Trapping Rain Water Problem's Link ------------------------------------------------------------- ... 
- 有意思的数学题:Trapping Rain Water
		LeetCode传送门 https://leetcode.com/problems/trapping-rain-water/ 目标:找出积木能容纳的水的“面积”,如图中黑色部分是积木,蓝色为可容纳水的 ... 
- [Leetcode][Python]42: Trapping Rain Water
		# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 42: Trapping Rain Waterhttps://oj.leetc ... 
- leetcode#42 Trapping rain water的五种解法详解
		leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ... 
- [array]  leetcode - 42. Trapping Rain Water - Hard
		leetcode - 42. Trapping Rain Water - Hard descrition Given n non-negative integers representing an e ... 
随机推荐
- Link & Redirect
			[Link] Link标签,用于实现React-Router功能的跳转.(意思是就不要使用a标签了) 1)to:string,指明要跳转的path. import { Link } from 'rea ... 
- new.target
			[new.target] The new.target property lets you detect whether a function or constructor was called us ... 
- Java8中的[方法引用]“双冒号”——走进Java Lambda(四)
			前面的章节我们提及到过双冒号运算符,双冒号运算就是Java中的[方法引用],[方法引用]的格式是 类名::方法名 注意是方法名哦,后面没有括号“()”哒.为啥不要括号,因为这样的是式子并不代表一定会调 ... 
- 【C++】子类访问父类typedef的问题
			class A { public: typedef int* pointer; }; class B :public A { public: pointer b; }; 这段代码运行没有问题,子类继承 ... 
- SoundChannel和soundTransform的关系
			SoundChannel 音乐的 播放 暂停 当前获取当前位置 长度 leftPeak : Number[只读] 左声道的当前幅度(音量),范围从 0(静音)至 1(最大幅度) rightPe ... 
- centos 7 下 cobbler 安装
			一.cobbler 介绍: Cobbler 是一个系统启动服务(boot server),可以通过网络启动(PXE)的方式用来快速安装.重装物理服务器和虚拟机,支持安装不同的 Linux 发行版和 W ... 
- hdu 5154 拓扑排序
			例题:hdu 5154 链接 http://acm.hdu.edu.cn/showproblem.php?pid=5154 题目意思是第一行先给出n和m表示有n件事,m个关系,接下来输入m行,每行有 ... 
- linux环境下的c++编程
			就C++开发工具而言,与Windows下微软(VC, VS2005等)一统天下相比,Linux/Unix下C++开发,可谓五花八门,各式各样.Emacs, vi, eclipse, anjuta,kd ... 
- Unity2017五子棋大战_人机_双人_UNET联网
			五子棋大战源码工程基于Unity2017.2进行开发,分为人机.双人.UNET网络三种对战方式,配有案例讲解视频, 其中人机五子棋AI有三种开发难度,欢迎有兴趣的同学加入学习! . 目录 000-展示 ... 
- winbox添加dhcp和nat
			例子如上,wan连接外网,lan作为内网. 设置网卡ip 保证mac地址正确! 去到ip address里,设置两网卡的ip! 保证能ping通外网! 设置dhcp ip pool添加池,192.16 ... 
