Trapping rain water
来源:互联网 发布:linux查cpu核数 编辑:程序博客网 时间:2024/05/01 08:27
题目描述
这道题可以借鉴直方图中求最大矩形面积的思想,是一道非常经典的题目,难度非常大,但是又经常在面试中出现。
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.For example,Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
分析
要理解本文的方法,可以先去看看陈利人老师提出的O(n)时间内解决直方图中最大矩形面积的问题很神奇的解法!怎么求柱状图中的最大矩形? ,如果网页上面无法查看图片,可以关注陈利人老师的微信公众号,上面还有一些其他的经典面试题。
算法的核心思想在于维护了一个非递减的栈,并考虑了相邻矩形之间的高度关系,具体请查看陈利人老师原文,这里不再详细讲解,可以理解了之后再继续阅读本文,也可以直接阅读本文。我将尝试着跟大家讲清楚!这里列出陈老师文章里的一张经的图片
回到本题:
什么样的情况才可能存水呢?只有两边的都比自己高,才有可能存水!如下图所示。
但是图形肯定不是如此简单的,如下图所示
使用一个非递增的栈stack, 也就是说(遍历数组遇到height[i]
比当前栈顶元素更大的元素时,需要将栈中所有比height[i]
小的元素出栈,只有这样才能维持栈的非递增顺序),那么在这些元素出栈时如何高效的计算和存储water量呢?
逐步填平凹陷的地方,如下图所示:
上面给出了计算的顺序,下面我们来逐步解释!
给定三个重要的量:
- 当前编号
i
- 当前栈顶元素
bot=stack[-1]
- 栈顶元素出栈之后新的栈顶元素
stack[-1]
根据这三个量的变化情况演示上面的图:
stack
是非递增的,可以知道当i=7
时,stack=[2,3,4,5,6]
.此时有stack[-1]=5,bot=6,i=7
,先计算途中紫色部分;此时栈顶元素5对应的高度还是小于i=7
的,继续出栈,stack[-1]=4,bot=5,i=7
,计算绿色部分。然后7本身是最小的了,入栈i=8
入栈i=9,stack=[2,3,4,7,8]
,8出栈,计算淡紫色部分;接着7出栈,计算蛋黄色部分;然后4出栈,计算红色部分;最后3出栈,计算桃红色部分;然后2出栈,此时栈已经为空,无需再计算。即得到了总体积水量。
注意:bot始终代表stack[-1]
和i
之间已经填平后的高度(注意分析这句话),新的积水量:
将所有的积水量相加就是最后的结果。
编码
stack = [] i = 0 maxwater = 0 while (i < len(height)): if len(stack) == 0 or (height[i] <= height[stack[-1]]): stack.append(i) i += 1 else: bot = stack[-1] stack.pop() if len(stack) == 0: water = 0 else: water = (min(height[i], height[stack[-1]]) - height[bot]) * (i - stack[-1] - 1) maxwater += water return maxwater
上述代码在leetcode上面并不是最优的,有兴趣的童鞋可以看看大神们的解法!下面我们跟踪一下代码,帮助理解算法,已经读懂的同学不用再看下面的!
示例
- 开始时
i=0,stack=[ ]
, 根据算法stack.append(i) i++
i=1,stack=[0]
,而栈顶元素高度小于当前i
的高度,出栈操作并且计算water=0:
当再次进入while
时,由于栈为空,直接将1
进栈,且i++
i=2,stack=[1],i=2
,当前元素高度小于栈顶元素高度,i
入栈i=3,stack=[1,2]
, 栈顶元素高度小于i
的高度(height[stack[-1]<height[i]]
),计算存水量:bot=stack.pop()
即bot=1
,栈非空:[0]
:(min(height[stack[-1]],height[i])-height[bot])*(i-stack[-1]-1)=(min(height[1],height[2])-height[2])*(2-0-1)=1
i=3,stack=[1]
,当前元素i
的高度大于栈顶,则出栈,此时栈为空,水量为0i=3,stack=[]
,直接将i
入栈,且i++
i=4,stack=[3]
,入栈且i++
i=5,stack=[3,4]
,还是入栈操作i=6,stack=[3,4,5]
,此时需要计算water了。先将5
出栈计算的雨量1.然后栈顶元素4, 该入栈了。i=7,stack=[3,4]
,大于栈顶元素,应该计算water,此时计算的是浅黄色的部分(原理我们稍后解释)i=7,stack=[3]
,出栈后为空,water=0,在下一步的while
中重新将i=7
入栈,一直继续下去…
阅读全文
0 0
- LeetCode: Trapping Rain Water
- LeetCode : Trapping Rain Water
- Trapping Rain Water
- [LeetCode] Trapping Rain Water
- [Leetcode] Trapping Rain Water
- [Leetcode] Trapping Rain Water
- Trapping Rain Water
- Trapping Rain Water
- [LeetCode]Trapping Rain Water
- Trapping Rain Water
- Trapping Rain Water
- LeetCode-Trapping Rain Water
- Trapping Rain Water
- [leetcode] Trapping Rain Water
- Trapping Rain Water
- [LeetCode] Trapping rain water
- Leetcode: Trapping Rain Water
- 38 - Trapping Rain Water
- 快速解读GC日志
- 用Seam实现:图片上传 + 保存到数据库 + 从数据库读出图片并显示到页面中
- 菜谱
- 开关电源设计中电感的选择
- java volatile
- Trapping rain water
- 匈牙利算法模板
- Kattis
- 删去单链表中第i个节点的操作。删除单链表中数据域为x的前驱元素。数据结构。
- SQL学习—INSERT、UPDATE、DELETE语句
- c++中的friend友元
- 【设计模式】-原型模式
- 344. Reverse String
- 每日一道算法题(7)