Leetcode 407. Trapping Rain Water II

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.

Leetcode 407. Trapping Rain Water II

The above image represents the elevation map [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain.

Leetcode 407. Trapping Rain Water II

After the rain, water are trapped between the blocks. The total volume of water trapped is 4.

(H) Trapping Rain Water
 

思路:与2D的管住两边的最低高度,3D只要管住包围的环中的最低高度就可以,保证最外围的单元一定在优先队列中,然后每次先遍历原先队列中高度最小的单元A,如果A的四周有尚未被遍历并且高度小于A的单元B,那么A的高度-B的高度就是新增加的蓄水体积,然后设置B的高度=max(A的高度,B的高度),将B加入优先队列。

另外一个需要注意的是解法中对类的比较的定义,Cell执行Comparable借口,重定义compareTo(Cell o)函数:返回负数意味着当前元素“小于”o,返回正数意味着当前元素“大于”o,返回0意味着当前元素“等于”o。

compareTo函数中定义成:

return this.height - o.height;

这就意味着this.height > o.height时,Comparable返回的是当前元素“大于”o;this.height < o.height时,Comparable返回的是当前元素“小于”o。又因为JAVA的PriorityQueue是小顶堆,因此队列的Cell是按height升序排列的。

那么,如果想要队列中的Cell按height降序排列,又可以怎么写? 

compareTo函数中可以定义成这样:

return o.height - this.height;

这就意味着如果this.height > o.height时,Comparable返回的是当前元素“小于”o,又因为JAVA的PriorityQueue是小顶堆,因此队列的当前元素排在o之前,也就是队列是按降序排列的。

代码:

 1 public class Solution {
 2      class Cell implements Comparable<Cell> {
 3         int row, col, height;
 4         public Cell(int row, int col, int height) {
 5             this.row = row;
 6             this.col = col;
 7             this.height = height;
 8         }
 9         //返回负数意味着当前元素“小于”o,返回正数意味着当前元素“大于”o,返回0意味着当前元素“等于”o
10         //JAVA中PriorityQueue默认的是小顶堆
11         public int compareTo(Cell o) {
12             return this.height - o.height;
13         }
14     }
15     
16     public int trapRainWater(int[][] heightMap) {
17         int n = heightMap.length, m = heightMap[0].length, res = 0;
18         int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
19         boolean[][] visited = new boolean[n][m];
20         PriorityQueue<Cell> queue = new PriorityQueue<Cell>();
21         for (int i = 0; i < n; ++i) {
22             visited[i][0] = visited[i][m - 1] = true;
23             queue.offer(new Cell(i, 0, heightMap[i][0]));
24             queue.offer(new Cell(i, m - 1, heightMap[i][m - 1]));
25         }
26         for (int i = 0; i < m; ++i) {
27             visited[0][i] = visited[n - 1][i] = true;
28             queue.offer(new Cell(0, i, heightMap[0][i]));
29             queue.offer(new Cell(n - 1, i, heightMap[n - 1][i]));
30         }
31         while (!queue.isEmpty()) {
32             Cell cell = queue.poll();
33             for (int i = 0; i < 4; ++i) {
34                 for (int j = 0; j < 2; ++j) {
35                     int row = cell.row + dirs[i][j];
36                     int col = cell.col + dirs[i][j];
37                     if (row > 0 && row < n && col > 0 && col < m && !visited[row][col]) {
38                         res += Math.max(0, cell.height - heightMap[row][col]);
39                         queue.offer(new Cell(row, col, Math.max(cell.height, heightMap[row][col])));
40                     }
41                 }
42             }
43         }
44         return res;
45     }
46 }