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.
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.
After the rain, water are trapped between the blocks. The total volume of water trapped is 4.
public class Solution {
class Cell {
int height, x, y;
public Cell(int _height, int _x, int _y) {
height = _height; x = _x; y = _y;
}
}
public int trapRainWater(int[][] heightMap) {
if (heightMap == null || heightMap.length == 0) {
return 0;
}
int m = heightMap.length;
int n = heightMap[0].length;
boolean[][] visited = new boolean[m][n];
PriorityQueue<Cell> queue = new PriorityQueue<Cell>(m * n, new Comparator<Cell>() {
public int compare(Cell c1, Cell c2) {
return c1.height - c2.height;
}
});
for (int i = 0; i < m; i++) {
queue.offer(new Cell(heightMap[i][0], i, 0));
visited[i][0] = true;
queue.offer(new Cell(heightMap[i][n - 1], i, n - 1));
visited[i][n - 1] = true;
}
for (int j = 1; j < n - 1; j++) {
queue.offer(new Cell(heightMap[0][j], 0, j));
visited[0][j] = true;
queue.offer(new Cell(heightMap[m - 1][j], m - 1, j));
visited[m - 1][j] = true;
}
int res = 0;
int[][] dirs = new int[][]{{0,1}, {0,-1}, {1,0}, {-1,0}};
while (!queue.isEmpty()) {
Cell cell = queue.poll();
for (int[] dir: dirs) {
int x = cell.x + dir[0], y = cell.y + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n && visited[x][y] == false) {
visited[x][y] = true;
if (heightMap[x][y] < cell.height) {
res += (cell.height - heightMap[x][y]);
queue.offer(new Cell(cell.height, x, y));
} else {
queue.offer(new Cell(heightMap[x][y], x, y));
}
}
}
}
return res;
}
}