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

猜你喜欢

转载自blog.csdn.net/yaoct/article/details/84559642