Analysis
It’s hard to start from inside the 2-D graph and find out the boarder of a crater. But if we start from the boarder and traverse into the graph from the smallest height of the boarders, we know we can trap some water once there is some height less than current height.
This is easy to solve with a minimum heap, since we only want to take out the smallest height among all boarders we have encountered.
So the algorithm is like following:
- store all of the boarders around the graph into a minimum heap. keep a 2-d boolean array visited to record the pointes already being visited.
- take out the smallest height and start searching its neighbors in 4 directions. If the point is not visited, consider following conditions:
- if the height of this point is less than current height, then this point can hold water of the size
(curr.height - thispoint.height), since current height is the smallest one among all the boarders and each point have a floor space of 1. After that, since this point is already filled with water, we should upgrade its height to current point’s height. - if the height of this point is greater than current height, then no water can be hold by this point, add this new point as a boarder into the minumum heap.
- if the height of this point is less than current height, then this point can hold water of the size
- loop until the minimum heap is empty.
Time and space complexity:
Heapify: O(m + n) time.
Then every point is put in and take out of the heap at most once. At the same time, we are doing so in a BFS style, meaning that there is m + n cells in the heap in the worst case. So the total time is O(m + n) + O(m * n * (log(m + n)) = O(m * n * (log(m + n)).
The space complexity would be (m * n) because of the visited array.
Implementation in Java
public class Solution {
class Cell {
int row;
int col;
int height;
public Cell(int row, int col, int height) {
this.row = row;
this.col = col;
this.height = height;
}
}
public int trapRainWater(int[][] heightMap) {
if (heightMap == null || heightMap.length == 0 || heightMap[0].length == 0) {
return 0;
}
Queue<Cell> heap = new PriorityQueue<Cell>(1, new Comparator<Cell>(){
@Override
public int compare(Cell a, Cell b) {
return a.height - b.height;
}
});
int ret = 0;
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;
heap.offer(new Cell(i, 0, heightMap[i][0]));
heap.offer(new Cell(i, n - 1, heightMap[i][n - 1]));
}
for (int i = 1; i < n - 1; i++) {
visited[0][i] = true;
visited[m - 1][i] = true;
heap.offer(new Cell(0, i, heightMap[0][i]));
heap.offer(new Cell(m - 1, i, heightMap[m - 1][i]));
}
int[][] dirs = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
while (!heap.isEmpty()) {
Cell curr = heap.poll();
for (int[] dir : dirs) {
int x = curr.row + dir[0];
int y = curr.col + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n && !visited[x][y]) {
visited[x][y] = true;
ret += Math.max(0, curr.height - heightMap[x][y]);
heap.offer(new Cell(x, y, Math.max(curr.height, heightMap[x][y])));
}
}
}
return ret;
}
}

本文介绍了一种利用最小堆解决二维地图中雨水捕捉问题的方法。通过遍历边界并将边界上的点加入最小堆,随后进行广度优先搜索来计算每个内部点能够保留的雨水量。
475

被折叠的 条评论
为什么被折叠?



