364. 接雨水 II
中文English
给出 n * m
个非负整数,代表一张X轴上每个区域为 1 * 1
的 2d 海拔图, 计算这个海拔图最多能接住多少(面积)雨水。
样例
样例 1:
例如,给定一个 5*4 的矩阵:
输入:
[[12,13,0,12],[13,4,13,12],[13,8,10,12],[12,13,12,12],[13,13,13,13]]
输出:
14
样例 2:
输入:
[[2,2,2,2],[2,2,3,4],[3,3,3,1],[2,3,4,5]]
输出:
0
输入测试数据 (每行一个参数)如何理解测试数据?
堆(最小堆) + 木桶原理(边界最小高度切入,由外及内)
边界最小的高度决定了里面存储的水量,当然内层如果存在高度更大的边界,存储的水量更多
import heapq class Solution: """ @param heights: a matrix of integers @return: an integer """ def __init__(self): self.borders = [] self.visited = set() def trapRainWater(self, heights): # write your code here #木桶原理,边界最小高度木板决定了里面的水量,由外向内遍历 #切入点,边界最小高度往里面切入 ''' 需要: self.visited = set() 已经访问过的不需要再进行访问,只需要x,y即可 heapq borders 堆里面存储的是所有的边界,包括x,y,height total 总水量 len_y, len_x 初始y轴和x轴长度 ''' if not heights: return 0 def adjust(x, y): new_array = [] direction = [[0, 1], [0, -1], [1, 0], [-1, 0]] for d in direction: new_x = x + d[0] new_y = y + d[1] if (0 <= new_x < self.len_y) and (0 <= new_y < self.len_x) and (new_x, new_y) not in self.visited: new_array.append((new_x, new_y)) return new_array #初始化 def initialize(heights): #找到所有的边界,x轴分别为0,len_x - 1 for i in range(self.len_y): add(i, 0, heights[i][0]) add(i, self.len_x - 1, heights[i][self.len_x - 1]) for j in range(self.len_x): add(0, j, heights[0][j]) add(self.len_y - 1, j, heights[self.len_y - 1][j]) def add(x, y, height): heapq.heappush(self.borders, [height, x, y]) self.visited.add((x, y)) total = 0 self.len_x, self.len_y = len(heights[0]), len(heights) initialize(heights) #从边界切入,每次去堆里面取最小值出来 while self.borders: cell_height, x, y = heapq.heappop(self.borders) #然后在当前切入的边界最小高度上下左右的找,如果小于,则存储水,否则0 for new_x, new_y in adjust(x, y): total += max(cell_height - heights[new_x][new_y], 0) #细节,后面height加的是内层的最大高度,因为最外层已经确定了所有高度,切入点也是从最外层最小高度开始切入的,内层的高度不影响了最外层高度,只能是比最外层最大高度高来影响里面 add(new_x, new_y, max(cell_height, heights[new_x][new_y])) return total