标签:
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
.
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!
和前面一题Container with Most Water是非常类似的题目。但是这题并非找两个边界使其面积最大,而是要求所有雨水的面积,所以还是很大区别的。
有多种解法,一种是基于栈的,另外一种两次扫描,获取每个柱子的左右两边最高的柱子,而每根柱子可以容纳的雨水就是min(max_left,max_right)。这是一次只算一根柱子的做法。栈的做法是每次横向算一个level(或多个level)的存储水量。
两次扫描的代码很好理解,我的实现如下:
class Solution(object): def trap(self, height): """ :type height: List[int] :rtype: int """ if not height or len(height) < 3: return 0 n = len(height) left = [height[0]] right = [height[-1]] #一次完成左右最高值的扫描 for i in xrange(1,n): if height[i-1] > left[-1]: left.append(height[i-1]) else: left.append(left[-1]) if height[n-i] > right[-1]: right.append(height[n-i]) else: right.append(right[-1]) water = 0
#计算面积 for i in xrange(1,n-1): res = min(left[i],right[~i]) - height[i] if res > 0: water += res return water
上述做法的时间复杂度为O(n),空间复杂度也为O(n),这种做法可以使用双指针使其空间复杂度降为O(1),详见leetcode discuss,我还没看懂。
基于栈的做法,是使用栈计算一个递减序列,对于栈顶元素来说,栈内倒数第二个元素都比其高,一旦当前遍历到的元素比栈顶要高,则可以计算栈顶这个bar为bottom可以存储的横向水量。所有元素都会执行一次入栈。代码如下:
class Solution(object): def trap(self, height): """ :type height: List[int] :rtype: int """ if not height or len(height) < 3: return 0 s = [] water = 0 maxBotwater = 0 i = 0 while i < len(height): if not s or height[i] <= height[s[-1]]: s.append(i) i += 1 else: bot = height[s.pop()] maxBotwater = 0 if not s else (min(height[s[-1]],height[i]) - bot)*(i-s[-1]-1) water += maxBotwater return water
具体解释参考leetcode discuss.这题理解的很不透彻,只需要再看。
标签:
原文地址:http://www.cnblogs.com/sherylwang/p/5540649.html