Java PriorityQueue Solution
\nclass Solution {\n    public int trapRainWater(int[][] heightMap) {\n        int nrow = heightMap.length;\n        if (heightMap.length == 0) {\n            r
```\nclass Solution {\n    public int trapRainWater(int[][] heightMap) {\n        int nrow = heightMap.length;\n        if (heightMap.length == 0) {\n            return 0;\n        }\n        int ncol = heightMap[0].length;\n        if (nrow < 3 || ncol < 3) {\n            return 0;\n        }\n        Queue<Point> heap = new PriorityQueue<>();\n        boolean[][] visited = new boolean[nrow][ncol];\n\t\t// push all border points to the heap. they are where we start our search.\n        initialization(heightMap, heap, visited, nrow, ncol);\n        int result = 0;\n        while (!heap.isEmpty()) {\n\t\t\t// poll out the point where we have the smallest height. like a bucket with shorted side.\n            Point curr = heap.poll();\n\t\t\t// generate neighbors of current point.\n            List<Point> neis = getNeis(curr, heightMap, visited, nrow, ncol);\n            for (Point nei : neis) {\n\t\t\t\t// if current point can hold water, add it to final result\n                result += Math.max(0, curr.h - nei.h);\n\t\t\t\t// set value for propagation\n                nei.h = Math.max(curr.h, nei.h);\n                heap.offer(nei);\n            }\n        }\n        return result;\n    }\n    \n    private void initialization(int[][] map, Queue<Point> heap, boolean[][] visited, int nrow, int ncol) {\n        for (int i = 0; i < nrow; i++) {\n            heap.offer(new Point(i, 0, map[i][0]));\n            heap.offer(new Point(i, ncol - 1, map[i][ncol - 1]));\n            visited[i][0] = true;\n            visited[i][ncol - 1] = true;\n        }\n        for (int i = 1; i < ncol - 1; i++) {\n            heap.offer(new Point(0, i, map[0][i]));\n            heap.offer(new Point(nrow - 1, i, map[nrow - 1][i]));\n            visited[0][i] = true;\n            visited[nrow - 1][i] = true;\n        }\n    }\n    \n    private List<Point> getNeis(Point curr, int[][] map, boolean[][] visited, int nrow, int ncol) {\n        List<Point> result = new ArrayList<>();\n        if (curr.r + 1 < nrow && !visited[curr.r + 1][curr.c]) {\n            result.add(new Point(curr.r + 1, curr.c, map[curr.r + 1][curr.c]));\n            visited[curr.r + 1][curr.c] = true;\n        }\n        if (curr.r - 1 >= 0 && !visited[curr.r - 1][curr.c]) {\n            result.add(new Point(curr.r - 1, curr.c, map[curr.r - 1][curr.c]));\n            visited[curr.r - 1][curr.c] = true;\n        }\n        if (curr.c + 1 < ncol && !visited[curr.r][curr.c + 1]) {\n            result.add(new Point(curr.r, curr.c + 1, map[curr.r][curr.c + 1]));\n            visited[curr.r][curr.c + 1] = true;\n        }\n        if (curr.c - 1 >= 0 && !visited[curr.r][curr.c - 1]) {\n            result.add(new Point(curr.r, curr.c - 1, map[curr.r][curr.c - 1]));\n            visited[curr.r][curr.c - 1] = true;\n        }\n        return result;\n    }\n    \n    static class Point implements Comparable<Point>{\n        int r;\n        int c;\n        int h;\n        public Point(int r, int c, int h) {\n            this.r = r;\n            this.c = c;\n            this.h = h;\n        }\n        @Override\n        public int compareTo(Point o) {\n            return Integer.compare(h, o.h);\n        }\n    }\n}\n\n```
[]