364. 接雨水 II

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
            

        
        
原文地址:https://www.cnblogs.com/yunxintryyoubest/p/13289645.html