Problem
Given an m x n
integer matrix heightMap
representing the height of each unit cell in a 2D elevation map, return the volume of water it can trap after raining.
Examples
Example 1:
Input:
heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
Output:
4
Explanation: After the rain, water is trapped between the blocks.
We have two small ponds 1 and 3 units trapped.
The total volume of water trapped is 4.
Example 2:
Input:
heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
Output:
10
Constraints:
m == heightMap.length
n == heightMap[i].length
1 <= m, n <= 200
0 <= heightMap[i][j] <= 2 * 104
Solution
Method 1 -
Code
C++
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
if(heightMap.empty() || heightMap[0].empty()) return 0;
int m = heightMap.size();
int n = heightMap[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
auto comp = [](const vector<int>& a, const vector<int>& b) {
return a[2] > b[2];
};
priority_queue<vector<int>, vector<vector<int>>, decltype(comp)> pq(comp);
for(int i = 0; i < m; ++i) {
pq.push({i, 0, heightMap[i][0]});
pq.push({i, n - 1, heightMap[i][n - 1]});
visited[i][0] = visited[i][n - 1] = true;
}
for(int j = 0; j < n; ++j) {
pq.push({0, j, heightMap[0][j]});
pq.push({m - 1, j, heightMap[m - 1][j]});
visited[0][j] = visited[m - 1][j] = true;
}
int ans = 0;
vector<int> dirs = {-1, 0, 1, 0, -1};
while(!pq.empty()) {
auto cell = pq.top();
pq.pop();
for(int k = 0; k < 4; ++k) {
int x = cell[0] + dirs[k];
int y = cell[1] + dirs[k + 1];
if(x >= 0 && x < m && y >= 0 && y < n && !visited[x][y]) {
visited[x][y] = true;
ans += max(0, cell[2] - heightMap[x][y]);
pq.push({x, y, max(cell[2], heightMap[x][y])});
}
}
}
return ans;
}
};
Go
type Cell struct {
x, y, h int
}
type MinHeap []Cell
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i].h < h[j].h }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x interface{}) {
*h = append(*h, x.(Cell))
}
func (h *MinHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func trapRainWater(heightMap [][]int) int {
if len(heightMap) == 0 || len(heightMap[0]) == 0 {
return 0
}
m, n := len(heightMap), len(heightMap[0])
visited := make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
h := &MinHeap{}
heap.Init(h)
for i := 0; i < m; i++ {
heap.Push(h, Cell{i, 0, heightMap[i][0]})
heap.Push(h, Cell{i, n - 1, heightMap[i][n - 1]})
visited[i][0] = true
visited[i][n-1] = true
}
for j := 0; j < n; j++ {
heap.Push(h, Cell{0, j, heightMap[0][j]})
heap.Push(h, Cell{m - 1, j, heightMap[m-1][j]})
visited[0][j] = true
visited[m-1][j] = true
}
ans := 0
dirs := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
for h.Len() > 0 {
cell := heap.Pop(h).(Cell)
for _, d := range dirs {
x, y := cell.x+d[0], cell.y+d[1]
if x >= 0 && x < m && y >= 0 && y < n && !visited[x][y] {
visited[x][y] = true
if cell.h > heightMap[x][y] {
ans += cell.h - heightMap[x][y]
}
heap.Push(h, Cell{x, y, max(cell.h, heightMap[x][y])})
}
}
}
return ans
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
Java
class Solution {
public int trapRainWater(int[][] heightMap) {
int m = heightMap.length, n = heightMap[0].length;
boolean[][] visited = new boolean[m][n];
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Integer.compare(a[2], b[2]));
for (int i = 0; i < m; i++) {
visited[i][0] = true;
visited[i][n - 1] = true;
pq.offer(new int[]{i, 0, heightMap[i][0]});
pq.offer(new int[]{i, n - 1, heightMap[i][n - 1]});
}
for (int j = 0; j < n; j++) {
visited[0][j] = true;
visited[m - 1][j] = true;
pq.offer(new int[]{0, j, heightMap[0][j]});
pq.offer(new int[]{m - 1, j, heightMap[m - 1][j]});
}
int[] dirs = {-1, 0, 1, 0, -1};
int ans = 0;
while (!pq.isEmpty()) {
int[] cell = pq.poll();
for (int k = 0; k < 4; k++) {
int x = cell[0] + dirs[k];
int y = cell[1] + dirs[k + 1];
if (x >= 0 && x < m && y >= 0 && y < n && !visited[x][y]) {
visited[x][y] = true;
ans += Math.max(0, cell[2] - heightMap[x][y]);
pq.offer(new int[]{x, y, Math.max(cell[2], heightMap[x][y])});
}
}
}
return ans;
}
}
Python
class Solution:
def trapRainWater(self, heightMap: List[List[int]]) -> int:
if not heightMap or not heightMap[0]:
return 0
m, n = len(heightMap), len(heightMap[0])
visited = [[False] * n for _ in range(m)]
pq = []
for i in range(m):
visited[i][0] = visited[i][n - 1] = True
heappush(pq, (heightMap[i][0], i, 0))
heappush(pq, (heightMap[i][n - 1], i, n - 1))
for j in range(n):
visited[0][j] = visited[m - 1][j] = True
heappush(pq, (heightMap[0][j], 0, j))
heappush(pq, (heightMap[m - 1][j], m - 1, j))
ans = 0
dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while pq:
h, x, y = heappop(pq)
for dx, dy in dirs:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
visited[nx][ny] = True
ans += max(0, h - heightMap[nx][ny])
heappush(pq, (max(h, heightMap[nx][ny]), nx, ny))
return ans
…
Complexity
- Time:
O(NNNXXXNNN)
- Space:
O(NNNXXX)