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 ...
 
随机推荐
- Java冒泡具体的原理,以及下标的变化
			
原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将 ...
 - with check(转)
			
假如我要为一个表中添加一个外键约束.语法如下 alter table dbo.employee with check add constraint [FK_employeeno] foreign ...
 - series of Nimble
			
[nimble] series方法用于串行执行多个异步任务,通过npm可安装nimble. Series works similarly to parallel, only it runs each ...
 - Appium1.6启动iOS真机
			
前提:已经安装了Appium1.6版本,我这里用的是GUI版本 环境要求: 真机iOS9.3及以上 macOS 10.11或10.12 Xcode7及以上 安装步骤如下 第一步:iOS真机 ...
 - yum更换阿里源
			
备份mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 下载新的CentOS-Base.repo ...
 - 调整数组顺序使奇数位于偶数前面(python)
			
题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. # -*- codi ...
 - 斐波那契数列(python)
			
题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 # -*- coding:utf-8 -*- class Solut ...
 - python基础入门学习简单程序练习
			
1.简单的乘法程序 i = 256*256 print('The value of i is', i) 运行结果: The value of i is 65536 2.执行python脚本的两种方式 ...
 - fragment 与activity通信 Bundle 序列化数据 Serializable
			
1.fragment简单套用(静态调用): 新建一个fragment,其xml文件如下: <LinearLayout xmlns:android="http://schemas.and ...
 - Genymotion 模拟器上网出现 net::ERR_NAME_NOT_RESOLVED
			
Genymotion 模拟器在公司网络安装的,然后启动能正常上网,把笔记本带回家,网络变化了,再使用模拟器 上网显示: (net::ERR_NAME_NOT_RESOLVED) 各种百度,最后用如下方 ...