LeetCode解题报告—— 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. Thanks Marcosfor contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
思路
Approach 1: Brute force
可以使用暴力破解的方法,即遍历所有的可能,从左往右遍历数组中的每个元素,找每个元素它左边最高的的高度max_left和它右边最高的高度max_right。计算这部分所能trap的水量,也就是max_left和max_right中的最小值减去这个元素的高度。换而言之,这种遍历的方法是遍历求每个横坐标单位上所能trap住的water,即 在这个单位横坐标上所能trap的water减去这个单位上竖条所占的面积:

代码:
class Solution {
public int trap(int[] height) {
int water=0;
for(int i=0;i<height.length;i++){
int max_left=0;
int max_right=0;
for(int j=i;j>=0;j--){
max_left=Math.max(max_left, height[j]);
}
for(int k=i;k<height.length;k++){
max_right=Math.max(max_right, height[k]);
}
water=water+Math.min(max_right, max_left)-height[i];
}
return water;
}
}
Approach 2: Dynamic Programming
方法一种会重复计算左边的max_left和右边的max_right,可以考虑使用dp的方法将已计算的结果存起来避免重复计算的问题。基本想法就是维持两个数组 left_max[i] 和right_max[i],分别存放位置i左边的最大高度和右边的最大高度,然后在再遍历一边数组元素即可。
具体的计算是这样的,对于right_max[i],如果i的高度比right_max[i-1]要高,也就是说位置i的bar的高度比之前高,那么right_max[i]等于height[i],否则就是之前最高的高度,也就是right_left[i-1],计算right_max同理。
代码:
class Solution {
public int trap(int[] height) {
int ans=0;
if(height==null || height.length==0) return ans;
int size=height.length;
int[] left_max=new int[size];
int[] right_max=new int[size];
left_max[0]=height[0];
right_max[size-1]=height[size-1];
for(int i=1;i<size;i++){
left_max[i]=Math.max(left_max[i-1], height[i]);
}
for(int i=size-2;i>=0;i--){
right_max[i]=Math.max(right_max[i+1], height[i]);
}
for(int i=0;i<size;i++){
ans+=Math.min(left_max[i], right_max[i])-height[i];
}
return ans;
}
}
Approach 3: Using stacks
方法三利用栈,遍历整个数组元素,如果当前bar的高度不大于栈顶的bar的高度(也就是不大于上一个bar),那么僵当前bar的索引加入到栈中。如果当前bar的高度大于栈顶bar的高度,可以的出一个结论是栈顶bar 是被当前 bar 和栈顶的前一个bar 困住的(bounded),所以我们能够弹出栈顶的bar并计算这个位置上所能trap的water。弹出栈顶计算完后,再判断当前current是否还是大于新的栈顶bar的高度,如果小于或等于则push入栈,否则继续按之前的执行。注意的是这种计算方法和解法一,解法二的本质不同在于,这个并不是按照单条bar来一个一个计算的,他是先判断两个bar构成的区域再乘以两个bar之间的距离这样来计算的,本质上是两种思路。
代码:
class Solution {
public int trap(int[] height) {
int ans=0;
if(height==null ) return ans;
Stack<Integer> st=new Stack();
int current=0;
while(current<height.length){
while(!st.isEmpty() && height[current]>height[st.peek()]){
int middle=st.peek();
st.pop();
if(st.isEmpty())
break;
int distance=current-st.peek()-1;// 算的是间隔距离,所以要减一
int bounded_height=Math.min(height[current], height[st.peek()])-height[middle];// 标记1
ans+=distance*bounded_height;
}
st.push(current++);
}
return ans;
}
}
标记1处开始看的时候不明白为什么要减去height[middle],其实想到(1)数组中有高度为0的bar也会被添加到栈中 (2)bar之间彼此临接。想到这两中情形的话就好理解多了。
还有Approach 4: Using 2 pointers方法,详细见:https://leetcode.com/problems/trapping-rain-water/solution/
LeetCode解题报告—— 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
Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...
- 【一天一道LeetCode】#42. Trapping Rain Water
一天一道LeetCode系列 (一)题目 Given n non-negative integers representing an elevation map where the width of ...
- 【LeetCode】42. Trapping Rain Water 接雨水 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 保存左右最大值 单调栈 日期 题目地址:ht ...
- leetcode problem 42 -- Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- LeetCode OJ 42. Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- 【LeetCode】042 Trapping Rain Water
题目: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...
- LeetCode: Trapping Rain Water 解题报告
https://oj.leetcode.com/problems/trapping-rain-water/ Trapping Rain WaterGiven n non-negative intege ...
- leetCode 42.Trapping Rain Water(凹槽的雨水) 解题思路和方法
Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...
随机推荐
- TYVJ2032 升降梯上
Description: 开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道.一辆停在轨道底部的电梯.和电梯内一杆控制电梯升降的巨大手柄.Nescafe ...
- ioctl函数用法小记
By francis_hao Aug 27,2017 UNPV1对ioctl有算是比较详细的介绍,但是,这些request和后面的数据类型是从哪里来的,以及参数具体该如何使用呢?本文尝试在不 ...
- Hadoop及Zookeeper+HBase完全分布式集群部署
Hadoop及HBase集群部署 一. 集群环境 系统版本 虚拟机:内存 16G CPU 双核心 系统: CentOS-7 64位 系统下载地址: http://124.202.164.6/files ...
- 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性.重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同.参数个数不同或者二者都不同)则视 ...
- HDU3308 线段树(区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- CMDB资产管理系统开发【day26】:CMDB上节回顾
一.上节知识点回顾 服务器设计了一个表结构 开发了一个客户端 二.后台创建缓存区表 客户端连接服务器,在服务器的下面看报错信息 因为URL都没有写,所以我找不到呀 1.在MadKing\url.py ...
- js实现游戏转盘抽奖
<!DOCTYPE html> <html> <head> <title>js抽奖</title> <meta charset=&qu ...
- ExtJS下拉列表使用方法(异步传输数据)
最近使用ExtJS下拉列表框(ComboBox)希望完成一个动态下拉列表的功能,即列表中的数据都通过异步方式查询数据库而来,同时在用户选择了列表中的某个值后,可以从后台正确的获取用户选择项所对应的值. ...
- mysql 中 group_concat()用法
基本语法:group_concat([DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator '分隔符']) 初始数据: ...
- LightOJ 1151 - Snakes and Ladders 高斯消元+概率DP
首先来个期望的论文,讲的非常好,里面也提到了使用线性方程组求解,尤其适用于有向图的期望问题. 算法合集之<浅析竞赛中一类数学期望问题的解决方法> http://www.lightoj.co ...