407. Trapping Rain Water II - jiejackyzhang/leetcode-note GitHub Wiki

Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

Note: Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:

Given the following 3x6 height map:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

Return 4.

解题思路为:可以存水的高度受到border中最矮的那一边的限制。 因此可以采用min heap来接,通过PriorityQueue实现。

  1. 首先将最外圈放入queue,并标记visited,最外圈不能往里注水。
  2. 然后取出最小的那个,考察它的四面,若unvisited并且比它低,则可以往里注水,并更新它的高度为注水后的高度,把它也放入queue,并标记visited。
  3. 直到all visited,则能注水的cell都已经注满水了。
public class Solution {
    class Cell {
        int x;
        int y;
        int h;
        public Cell(int x, int y, int h) {
            this.x = x;
            this.y = y;
            this.h = h;
        }
    }
    
    public int trapRainWater(int[][] heightMap) {
        if(heightMap == null || heightMap.length <= 1 || heightMap[0].length <= 1) return 0;
        PriorityQueue<Cell> queue = new PriorityQueue<Cell>(1, new Comparator<Cell>(){
            public int compare(Cell A, Cell B) {
                return A.h - B.h;
            }
        });
        int m = heightMap.length;
        int n = heightMap[0].length;
        boolean[][] visited = new boolean[m][n];
        for(int i = 0; i < m; i++) {
            visited[i][0] = true;
            visited[i][n-1] = true;
            queue.offer(new Cell(i, 0, heightMap[i][0]));
            queue.offer(new Cell(i, n-1, heightMap[i][n-1]));
        }
        for(int j = 0; j < n; j++) {
            visited[0][j] = true;
            visited[m-1][j] = true;
            queue.offer(new Cell(0, j, heightMap[0][j]));
            queue.offer(new Cell(m-1, j, heightMap[m-1][j]));
        }
        int[][] directions = {{0,1},{0,-1},{1,0},{-1,0}};
        int sum = 0;
        while (!queue.isEmpty()) {
            Cell cell = queue.poll();
            for (int i = 0; i < 4; i++) {
                int x = cell.x + directions[i][0];
                int y = cell.y + directions[i][1];
                if (x >= 0 && x < m && y >= 0 && y < n && !visited[x][y]) {
                    visited[x][y] = true;
                    sum += Math.max(0, cell.h - heightMap[x][y]);
                    queue.offer(new Cell(x, y, Math.max(heightMap[x][y], cell.h)));
                }
            }
        }
        return sum;
    }
}
⚠️ **GitHub.com Fallback** ⚠️