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的更多相关文章

  1. [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 ...

  2. [LeetCode] Trapping Rain Water 收集雨水

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  3. [LintCode] Trapping Rain Water 收集雨水

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  4. LeetCode:Container With Most Water,Trapping Rain Water

    Container With Most Water 题目链接 Given n non-negative integers a1, a2, ..., an, where each represents ...

  5. LeetCode - 42. Trapping Rain Water

    42. Trapping Rain Water Problem's Link ------------------------------------------------------------- ...

  6. 有意思的数学题:Trapping Rain Water

    LeetCode传送门 https://leetcode.com/problems/trapping-rain-water/ 目标:找出积木能容纳的水的“面积”,如图中黑色部分是积木,蓝色为可容纳水的 ...

  7. [Leetcode][Python]42: Trapping Rain Water

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 42: Trapping Rain Waterhttps://oj.leetc ...

  8. leetcode#42 Trapping rain water的五种解法详解

    leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...

  9. [array] leetcode - 42. Trapping Rain Water - Hard

    leetcode - 42. Trapping Rain Water - Hard descrition Given n non-negative integers representing an e ...

随机推荐

  1. lvm磁盘分区

    初始分区情况见下: 创建lvm类型磁盘 创建卷pv 添加pv到vg中,vg名vgroup0 创建lv lvcreate -L 2g -n zookeeper vgroup0 在vg vgroup0中创 ...

  2. SXSSExcelUtil

    package com.numa.util; import org.apache.poi.hssf.usermodel.HSSFCell;import org.apache.poi.hssf.util ...

  3. 开启swap交换分区

    开启swap 1.创建用于交换分区的文件: dd if=/dev/zero of=/mnt/swap bs=1M count=2048 注:block_size.number_of_block 大小可 ...

  4. linux 根据服务名称批量杀死进程

    ps -ef |grep python |awk '{print $2}'|xargs kill -9

  5. Android 7.0解决抓取不到https请求的问题

    问题:Android7.0系统,使用fiddler不能抓取https请求 解决方法:  1.在源码res目录下新建xml目录,增加network_security_config.xml文件 (工程名/ ...

  6. Bar-Code-Recognition-System Private

    本设计研究EAN13条形码识别的译码技术,在基于机器视觉技术上,构建了一套条形码在线检测识别系统,系统将由以下几个部分构成:条形码图像定位与采集.计算机图像预处理.条形码图像中值滤波去噪.条码解析与识 ...

  7. [剑指Offer]11-旋转数组的最小数字(二分查找)

    题目链接 https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159&t ...

  8. 高盛昂赛 算法题先写corner case

    [方法] 字写大点,先注释框架 链表:指针走就行了,最多是两个同时一起走. 两个链表求交点 //corner case if (headA == null || headB == null) { re ...

  9. MD5加密和sha加密

    sha加密原理Algorithm)又叫安全哈希加密技术,是当今世界最先近的加密算法.主要用于文件身份识别.数字签名和口令加密等. 对于明文信息A,通过SHA1算法,生成一条160位长的识别码B.且明文 ...

  10. JS编程题练习

    JS编程题练习 1. 两个数组合并成一个数组排序返回 先依次比较两个数组,按照小的就传入新的数组.当这次比较完之后可能有一个数组的长度很长,留下一些数组,然后在新数组的末尾插入即可. function ...