Java O(N*M*Log(N*M)) using priority queue clean approach
\nclass Solution {\n    public int trapRainWater(int[][] heightMap) {\n        PriorityQueue<int[]> priQueue = new PriorityQueue<>(\n            (a, b) -> heigh
```\nclass Solution {\n    public int trapRainWater(int[][] heightMap) {\n        PriorityQueue<int[]> priQueue = new PriorityQueue<>(\n            (a, b) -> heightMap[a[0]][a[1]] - heightMap[b[0]][b[1]]\n        );\n        int N = heightMap.length, M = heightMap[0].length;\n        boolean[][] visited = new boolean[N][M];\n        \n        // fill top and bottom boundaries\n        for(int col = 0; col < M; col++){\n            priQueue.add(new int[]{0, col});\n            priQueue.add(new int[]{N - 1, col});\n            visited[0][col] = true;\n            visited[N - 1][col] = true;\n        }\n        \n        // fill left and right boundaries\n        for(int row = 0; row < N; row++){\n            priQueue.add(new int[]{row, 0});\n            priQueue.add(new int[]{row, M - 1});\n            visited[row][0] = true;\n            visited[row][M - 1] = true;\n        }\n        \n        int totalTrappedWater = 0, max = -1;\n        int[][] directions = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};\n        \n        while(!priQueue.isEmpty()){\n            int[] curr = priQueue.poll();\n            max = Math.max(max, heightMap[curr[0]][curr[1]]);\n            totalTrappedWater += max - heightMap[curr[0]][curr[1]];\n            \n            for(int[] direct : directions){\n                int newRow = curr[0] + direct[0];\n                int newCol = curr[1] + direct[1];\n                \n                if(newRow < 0 || newCol < 0 || newRow == N || newCol == M || visited[newRow][newCol]){\n                    continue;\n                }\n                \n                priQueue.add(new int[]{newRow, newCol});\n                visited[newRow][newCol] = true;\n            }\n        }\n        \n        return totalTrappedWater;\n    }\n}\n```
['Java']