leetcode 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,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