[LeetCode] Problem 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
2
3
4
5
[
[1,4,3,1,3,2],
[3,2,1,3,2,4],
[2,3,3,2,3,1]
]

Return 4.

ZjgF9H.png

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.

ZjgZut.png

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

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class Cell{
private int x;
private int y;
private 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 == 0 || heightMap[0].length == 0)
return 0;

int result = 0;
int m = heightMap.length;
int n = heightMap[0].length;
boolean[][] visit = new boolean[m][n];
int[][] directions = new int[][] {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int level = 0;

PriorityQueue<Cell> minHeap = new PriorityQueue<>(new Comparator<Cell>() {
@Override
public int compare(Cell o1, Cell o2) {
return o1.h - o2.h;
}
});

for (int i = 0; i < n; i++) {
minHeap.offer(new Cell(0, i, heightMap[0][i]));
minHeap.offer(new Cell(m - 1, i, heightMap[m - 1][i]));
visit[0][i] = true;
visit[m - 1][i] = true;
}

for (int i = 1; i < m - 1; i++) {
minHeap.offer(new Cell(i, 0, heightMap[i][0]));
minHeap.offer(new Cell(i, n - 1, heightMap[i][n - 1]));
visit[i][0] = true;
visit[i][n - 1] = true;
}

while (!minHeap.isEmpty()) {
Cell cell = minHeap.poll();
level = Math.max(level, cell.h);

for (int[] direction : directions) {
int x = cell.x + direction[0];
int y = cell.y + direction[1];

if (x < 0 || y < 0 || x >= m || y >= n || visit[x][y])
continue;

if (heightMap[x][y] < level)
result += level - heightMap[x][y];

visit[x][y] = true;
minHeap.offer(new Cell(x, y, heightMap[x][y]));
}
}

return result;
}