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 is trapped between the blocks. The total volume of water trapped is 4.
思路:由Trapping Rain Water二维问题的其中一种解法想到,可以从边缘开始下手。把边缘的点放入一个PriorityQueue。然后由最小的点开始BFS,如果BFS到的点如果小于PriorityQueue中的最小值,放入一个Queue里面,可以直接求出此点的容量。如果BFS到的点大于PriorityQueue中的最小值,则把此点放入PriorityQueue,作为之后的边缘点。
class Solution {
class Point{
int x;
int y;
Point(int x,int y){
this.x=x;
this.y=y;
}
}
public int trapRainWater(int[][] heightMap) {
if(heightMap==null||heightMap.length<=2||heightMap[0].length<=2) return 0;
PriorityQueue<Point> pq=new PriorityQueue<>(new Comparator<Point>(){
public int compare(Point p1,Point p2){
return heightMap[p1.x][p1.y]-heightMap[p2.x][p2.y];
}
});
LinkedList<Point> queue=new LinkedList<>();
boolean[][] visited=new boolean[heightMap.length][heightMap[0].length];
for(int j=0;j<heightMap[0].length;j++) pq.offer(new Point(0,j));
for(int j=0;j<heightMap[0].length;j++) pq.offer(new Point(heightMap.length-1,j));
for(int i=1;i<heightMap.length-1;i++) pq.offer(new Point(i,0));
for(int i=1;i<heightMap.length-1;i++) pq.offer(new Point(i,heightMap[0].length-1));
int[][] dir={{0,1},{0,-1},{1,0},{-1,0}};
int count=0;
while(pq.size()>0){
queue.add(pq.peek());//基于pq的最小值的一次BFS
while(queue.size()>0){
Point p=queue.poll();
for(int i=0;i<4;i++){
int x=p.x+dir[i][0];
int y=p.y+dir[i][1];
if(x<1||x>=heightMap.length-1||y<1||y>=heightMap[0].length-1||visited[x][y]){
continue;
}
visited[x][y]=true;
if(heightMap[x][y]>heightMap[pq.peek().x][pq.peek().y]){
pq.offer(new Point(x,y));//记录大于,之后最为边缘点
}else{
queue.add(new Point(x,y));//记录小于,直接求出容量
count+=heightMap[pq.peek().x][pq.peek().y]-heightMap[x][y];
}
}
}
pq.poll();
}
return count;
}
}
讨论区有个做法不需要Queue。思路是用Point中记录高度,对于小于当前高度的点,用当前高度代替,再加到优先队列就可以了。
https://leetcode.com/problems/trapping-rain-water-ii/discuss/89461/Java-solution-using-PriorityQueue