import heapq
class Solution:
def trapRainWater(self, heightMap):
if not heightMap or not heightMap[0]:
return 0
m, n = len(heightMap), len(heightMap[0])
visited = [[False] * n for _ in range(m)]
heap = []
# Add all the boundary cells to the heap
for i in range(m):
for j in [0, n-1]:
heapq.heappush(heap, (heightMap[i][j], i, j))
visited[i][j] = True
for j in range(n):
for i in [0, m-1]:
if not visited[i][j]:
heapq.heappush(heap, (heightMap[i][j], i, j))
visited[i][j] = True
water = 0
dirs = [(-1,0), (1,0), (0,-1), (0,1)]
while heap:
height, x, y = heapq.heappop(heap)
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
water += max(0, height - heightMap[nx][ny])
heapq.heappush(heap, (max(height, heightMap[nx][ny]), nx, ny))
return water
#include <vector>
#include <queue>
using namespace std;
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
int m = heightMap.size();
if (m == 0) return 0;
int n = heightMap[0].size();
if (n == 0) return 0;
vector<vector<bool>> visited(m, vector<bool>(n, false));
using Cell = tuple<int, int, int>; // height, x, y
priority_queue<Cell, vector<Cell>, greater<Cell>> heap;
// Push boundary cells
for (int i = 0; i < m; ++i) {
heap.emplace(heightMap[i][0], i, 0);
visited[i][0] = true;
heap.emplace(heightMap[i][n-1], i, n-1);
visited[i][n-1] = true;
}
for (int j = 1; j < n-1; ++j) {
heap.emplace(heightMap[0][j], 0, j);
visited[0][j] = true;
heap.emplace(heightMap[m-1][j], m-1, j);
visited[m-1][j] = true;
}
int dirs[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
int water = 0;
while (!heap.empty()) {
auto [h, x, y] = heap.top(); heap.pop();
for (auto& d : dirs) {
int nx = x + d[0], ny = y + d[1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n || visited[nx][ny]) continue;
visited[nx][ny] = true;
water += max(0, h - heightMap[nx][ny]);
heap.emplace(max(h, heightMap[nx][ny]), nx, ny);
}
}
return water;
}
};
import java.util.*;
class Solution {
public int trapRainWater(int[][] heightMap) {
int m = heightMap.length;
if (m == 0) return 0;
int n = heightMap[0].length;
if (n == 0) return 0;
boolean[][] visited = new boolean[m][n];
PriorityQueue<int[]> heap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
// Push boundary cells
for (int i = 0; i < m; i++) {
heap.offer(new int[]{heightMap[i][0], i, 0});
visited[i][0] = true;
heap.offer(new int[]{heightMap[i][n-1], i, n-1});
visited[i][n-1] = true;
}
for (int j = 1; j < n-1; j++) {
heap.offer(new int[]{heightMap[0][j], 0, j});
visited[0][j] = true;
heap.offer(new int[]{heightMap[m-1][j], m-1, j});
visited[m-1][j] = true;
}
int[][] dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};
int water = 0;
while (!heap.isEmpty()) {
int[] cell = heap.poll();
int h = cell[0], x = cell[1], y = cell[2];
for (int[] d : dirs) {
int nx = x + d[0], ny = y + d[1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n || visited[nx][ny]) continue;
visited[nx][ny] = true;
water += Math.max(0, h - heightMap[nx][ny]);
heap.offer(new int[]{Math.max(h, heightMap[nx][ny]), nx, ny});
}
}
return water;
}
}
class MinHeap {
constructor() { this.data = []; }
push(val) {
this.data.push(val);
this._bubbleUp(this.data.length - 1);
}
pop() {
if (this.data.length === 1) return this.data.pop();
const top = this.data[0];
this.data[0] = this.data.pop();
this._bubbleDown(0);
return top;
}
_bubbleUp(idx) {
while (idx > 0) {
let parent = Math.floor((idx - 1) / 2);
if (this.data[parent][0] <= this.data[idx][0]) break;
[this.data[parent], this.data[idx]] = [this.data[idx], this.data[parent]];
idx = parent;
}
}
_bubbleDown(idx) {
let length = this.data.length;
while (true) {
let left = idx * 2 + 1, right = idx * 2 + 2, smallest = idx;
if (left < length && this.data[left][0] < this.data[smallest][0]) smallest = left;
if (right < length && this.data[right][0] < this.data[smallest][0]) smallest = right;
if (smallest === idx) break;
[this.data[smallest], this.data[idx]] = [this.data[idx], this.data[smallest]];
idx = smallest;
}
}
isEmpty() { return this.data.length === 0; }
}
var trapRainWater = function(heightMap) {
if (!heightMap.length || !heightMap[0].length) return 0;
let m = heightMap.length, n = heightMap[0].length;
let visited = Array.from({length: m}, () => Array(n).fill(false));
let heap = new MinHeap();
// Push boundary cells
for (let i = 0; i < m; i++) {
heap.push([heightMap[i][0], i, 0]);
visited[i][0] = true;
heap.push([heightMap[i][n-1], i, n-1]);
visited[i][n-1] = true;
}
for (let j = 1; j < n-1; j++) {
heap.push([heightMap[0][j], 0, j]);
visited[0][j] = true;
heap.push([heightMap[m-1][j], m-1, j]);
visited[m-1][j] = true;
}
let dirs = [[-1,0],[1,0],[0,-1],[0,1]];
let water = 0;
while (!heap.isEmpty()) {
let [h, x, y] = heap.pop();
for (let [dx, dy] of dirs) {
let nx = x + dx, ny = y + dy;
if (nx < 0 || nx >= m || ny < 0 || ny >= n || visited[nx][ny]) continue;
visited[nx][ny] = true;
water += Math.max(0, h - heightMap[nx][ny]);
heap.push([Math.max(h, heightMap[nx][ny]), nx, ny]);
}
}
return water;
};
heightMap
representing an elevation map where heightMap[i][j]
is the height of the terrain at cell (i, j)
, compute how much water it is able to trap after raining.
m == heightMap.length
n == heightMap[i].length
1 <= m, n <= 200
0 <= heightMap[i][j] <= 2 * 10^4
max(0, current_height - neighbor_height)
.max(current_height, neighbor_height)
as its new height (the wall is now at least as high as the highest of the two).heightMap = [ [1, 4, 3, 1, 3, 2], [3, 2, 1, 3, 2, 4], [2, 3, 3, 2, 3, 1] ]Step-by-step: