407 Trapping Rain Water II
Problem:
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.
Solutions:
See this article
public class Solution {
private class Node implements Comparable<Node>{
public int x;
public int y;
public int h;
public Node(int x, int y, int h) {
this.x = x;
this.y = y;
this.h = h;
}
public int compareTo(Node n) {
return this.h - n.h;
}
}
public int trapRainWater(int[][] heightMap) {
int[][] hm = heightMap;
if (hm == null || hm.length == 0 || hm[0].length == 0) {
return 0;
}
PriorityQueue<Node> q = new PriorityQueue<Node>();
int m = hm.length, n = hm[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i ++) {
q.add(new Node(i, 0, hm[i][0]));
q.add(new Node(i, n - 1, hm[i][n - 1]));
visited[i][0] = true;
visited[i][n - 1] = true;
}
for (int j = 0; j < n; j ++) {
q.add(new Node(0, j, hm[0][j]));
q.add(new Node(m - 1, j, hm[m - 1][j]));
visited[0][j] = true;
visited[m - 1][j] = true;
}
int level = Integer.MIN_VALUE;
int water = 0;
int[][] dir = new int[][]{{0, 1},{0, -1},{1, 0},{-1, 0}};
while (!q.isEmpty()) {
Node node = q.poll();
int x = node.x, y = node.y, h = node.h;
if (h < level) {
water += level - h;
}
level = Math.max(level, h);
for (int k = 0; k < dir.length; k ++) {
int nx = x + dir[k][0];
int ny = y + dir[k][1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
continue;
}
if (visited[nx][ny] == true) {
continue;
}
q.add(new Node(nx, ny, hm[nx][ny]));
visited[nx][ny] = true;
}
}
return water;
}
}