LeetCode: 42. 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 Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
就是每个位置给定一个海拔高度,宽度都是1,求下雨注满水之后这个横切面的面积是多少。
思路一:暴力求解法
我们从垂直方向上切分每个位置,例如这里的位置4,这个位置的需水量的高度是它左右两侧最高值中的较小值,比如左侧最高值是2,右侧最高值是3,但是很显然要取较小值2,所以它的水位高度是2,但是由于它本身海拔是1,所以还要减去1。这样遍历每个位置,求出各自位置上的面积,再相加,即可得出结果,代码如下:
class Solution:
def trap(self, height: List[int]) -> int:
ans = 0
size = len(height)
for i in range(size):
max_left = 0
max_right = 0
for j in range(0,i+1)[::-1]:
# Search the left part for max bar size
max_left = max(max_left, height[j])
for j in range(i,size):
# Search the right part for max bar size
max_right = max(max_right, height[j])
ans += min(max_left, max_right) - height[i]
return ans;
但是这样的时间复杂度是 O ( n 2 ) O(n^2) O(n2),不能ac。继续考虑其他方法。
思路二:动态规划
刚刚的暴力求解法,每次都要遍历左右两侧寻找最高值,其实每个位置的左右两侧最高值只要通过一次遍历保存即可。
class Solution:
def trap(self, height: List[int]) -> int:
if (height is None or len(height) == 0):
return 0
ans = 0
size = len(height)
left_max = [0] * size
right_max = [0] * size
left_max[0] = height[0]
for i in range(size):
left_max[i] = max(height[i], left_max[i - 1])
right_max[size - 1] = height[size - 1]
for i in range(0,size - 1)[::-1] :
right_max[i] = max(height[i], right_max[i + 1])
for i in range(0,size-1):
ans += min(left_max[i], right_max[i]) - height[i]
return ans
这样的时间复杂度是O(n)
THE END.