 GFG App
Open App Browser
Continue

# Trapping Rain Water in a Matrix

Given a matrix arr[][] of dimension M*N consisting of positive integers, where arr[i][j] represents the height of each unit cell, the task is to find the total volume of water trapped in the matrix after rain.

Examples:

Input: arr[][] = {{4, 2, 7}, {2, 1, 10}, {5, 10, 2}}
Output: 1
Explanation:
The rain water can be trapped in the following way:

1. The cells, {(0, 0), (0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1), (2, 2)} traps 0 unit volume of rain water as all water goes out of the matrix as cells are on the boundary.
2. The cell (2, 2) traps 1 unit volume of rain water in between the cells {(0, 1), (1, 0), (1, 2), and (2, 1)}.

Therefore, a total of 1 unit volume of rain water has been trapped inside the matrix.

Input: arr[][] = {{1, 4, 3, 1, 3, 2}, {3, 2, 1, 3, 2, 4}, {2, 3, 3, 2, 3, 1}}
Output: 4

Approach: The given problem can be solved by using the Greedy Technique and Min-Heap. Follow the steps below to solve the problem:

• Initialize a Min-Heap using the priority_queue, say PQ, to store the pairs of positions of a cell and its height.
• Push all the boundary cells in the PQ and mark all the pushed cells as visited.
• Initialize two variables, say ans as 0 and maxHeight as 0 to store the total volume and the maximum height of all the cells in PQ respectively.
• Iterate until PQ is not empty and perform the following steps:
• Store the top node of PQ in a variable, say front, and erase the top element of PQ.
• Update the value of maxHeight as the maximum of maxHeight and front.height.
• Now, traverse to all the adjacent nodes of the current cell (front.X, front.Y) and do the following:
• If the adjacent cell is valid i.e, the cell is not out of bound and not yet visited, then, push the value of the adjacent cell into PQ.
• If the height of the adjacent cell is less than maxHeight then increment the ans by the difference of maxHeight and the height of the adjacent cell.
• Finally, after completing the above steps, print the value of ans as the resultant water trapped after rain.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach` `#include ` `using` `namespace` `std;`   `// Stores the direction of all the` `// adjacent cells` `vector > dir` `    ``= { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };`   `// Node structure` `struct` `node {`   `    ``int` `height;` `    ``int` `x, y;` `};`   `// Comparator function to implement` `// the min heap using priority queue` `struct` `Compare {`   `    ``// Comparator function` `    ``bool` `operator()(node ``const``& a, node ``const``& b)` `    ``{` `        ``return` `a.height > b.height;` `    ``}` `};`   `// Function to find the amount of water` `// the matrix is capable to hold` `int` `trapRainWater(vector >& heightMap)` `{` `    ``int` `M = heightMap.size();` `    ``int` `N = heightMap.size();`   `    ``// Stores if a cell of the matrix` `    ``// is visited or not` `    ``vector > visited(M,` `                                  ``vector<``bool``>(N, ``false``));`   `    ``// Initialize a priority queue` `    ``priority_queue, Compare> pq;`   `    ``// Traverse over the matrix` `    ``for` `(``int` `i = 0; i < M; i++) {` `        ``for` `(``int` `j = 0; j < N; j++) {`   `            ``// If element is not on` `            ``// the boundary` `            ``if` `(!(i == 0 || j == 0 || i == M - 1` `                  ``|| j == N - 1))` `                ``continue``;`   `            ``// Mark the current cell` `            ``// as visited` `            ``visited[i][j] = ``true``;`   `            ``// Node for priority queue` `            ``node t;` `            ``t.x = i;` `            ``t.y = j;` `            ``t.height = heightMap[i][j];`   `            ``// Pushe all the adjacent` `            ``// node in the pq` `            ``pq.push(t);` `        ``}` `    ``}`   `    ``// Stores the total volume` `    ``int` `ans = 0;`   `    ``// Stores the maximum height` `    ``int` `max_height = INT_MIN;`   `    ``// Iterate while pq is not empty` `    ``while` `(!pq.empty()) {`   `        ``// Store the top node of pq` `        ``node front = pq.top();`   `        ``// Delete the top element of pq` `        ``pq.pop();`   `        ``// Update the max_height` `        ``max_height = max(max_height, front.height);`   `        ``// Stores the position of the` `        ``// current cell` `        ``int` `curr_x = front.x;` `        ``int` `curr_y = front.y;`   `        ``for` `(``int` `i = 0; i < 4; i++) {`   `            ``int` `new_x = curr_x + dir[i];` `            ``int` `new_y = curr_y + dir[i];`   `            ``// If adjacent cells are out` `            ``// of bound or already visited` `            ``if` `(new_x < 0 || new_y < 0 || new_x >= M` `                ``|| new_y >= N || visited[new_x][new_y]) {` `                ``continue``;` `            ``}`   `            ``// Stores the height of the` `            ``// adjacent cell` `            ``int` `height = heightMap[new_x][new_y];`   `            ``// If height of current cell` `            ``// is smaller than max_height` `            ``if` `(height < max_height) {`   `                ``// Increment the ans by` `                ``// (max_height-height)` `                ``ans = ans + (max_height - height);` `            ``}`   `            ``// Define a new node` `            ``node temp;` `            ``temp.x = new_x;` `            ``temp.y = new_y;` `            ``temp.height = height;`   `            ``// Push the current node` `            ``// in the pq` `            ``pq.push(temp);`   `            ``// Mark the current cell` `            ``// as visited` `            ``visited[new_x][new_y] = ``true``;` `        ``}` `    ``}`   `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{` `    ``vector > arr = { { 1, 4, 3, 1, 3, 2 },` `                                 ``{ 3, 2, 1, 3, 2, 4 },` `                                 ``{ 2, 3, 3, 2, 3, 1 } };` `    ``cout << trapRainWater(arr);`   `    ``return` `0;` `}`

## Java

 `// Java Program for above approach` `import` `java.util.*;`   `// Node structure` `class` `node {` `  ``int` `height;` `  ``int` `x, y;` `}`   `// Comparator function to implement` `// the min heap using priority queue` `class` `Compare ``implements` `Comparator {` `  ``public` `int` `compare(node a, node b) {` `    ``return` `a.height - b.height;` `  ``}` `}`   `class` `Main {` `  ``// Stores the direction of all the` `  ``// adjacent cells` `  ``static` `int``[][] dir = { { -``1``, ``0` `}, { ``0``, ``1` `}, { ``1``, ``0` `}, { ``0``, -``1` `} };`   `  ``// Function to find the amount of water` `  ``// the matrix is capable to hold` `  ``static` `int` `trapRainWater(``int``[][] heightMap) {` `    ``int` `M = heightMap.length;` `    ``int` `N = heightMap[``0``].length;`   `    ``// Stores if a cell of the matrix` `    ``// is visited or not` `    ``boolean``[][] visited = ``new` `boolean``[M][N];`     `    ``// Initialize a priority queue` `    ``PriorityQueue pq = ``new` `PriorityQueue(``new` `Compare());`   `    ``// Traverse over the matrix` `    ``for` `(``int` `i = ``0``; i < M; i++) {` `      ``for` `(``int` `j = ``0``; j < N; j++) {`   `        ``// If element is not on` `        ``// the boundary` `        ``if` `(!(i == ``0` `|| j == ``0` `|| i == M - ``1` `|| j == N - ``1``))` `          ``continue``;`   `        ``// Mark the current cell` `        ``// as visited` `        ``visited[i][j] = ``true``;`   `        ``// Node for priority queue` `        ``node t = ``new` `node();` `        ``t.x = i;` `        ``t.y = j;` `        ``t.height = heightMap[i][j];`   `        ``// Pushe all the adjacent` `        ``// node in the pq` `        ``pq.offer(t);` `      ``}` `    ``}`   `    ``// Stores the total volume` `    ``int` `ans = ``0``;`     `    ``// Stores the maximum height` `    ``int` `max_height = Integer.MIN_VALUE;`   `    ``// Iterate while pq is not empty` `    ``while` `(!pq.isEmpty()) {`   `      ``// Store the top node of pq` `      ``node front = pq.poll();`   `      ``// Update the max_height` `      ``max_height = Math.max(max_height, front.height);`   `      ``// Stores the position of the` `      ``// current cell` `      ``int` `curr_x = front.x;` `      ``int` `curr_y = front.y;`   `      ``for` `(``int` `i = ``0``; i < ``4``; i++) {`   `        ``int` `new_x = curr_x + dir[i][``0``];` `        ``int` `new_y = curr_y + dir[i][``1``];`   `        ``// If adjacent cells are out` `        ``// of bound or already visited` `        ``if` `(new_x < ``0` `|| new_y < ``0` `|| new_x >= M || new_y >= N || visited[new_x][new_y]) {` `          ``continue``;` `        ``}`     `        ``// Stores the height of the` `        ``// adjacent cell` `        ``int` `height = heightMap[new_x][new_y];`   `        ``// If height of current cell` `        ``// is smaller than max_height` `        ``if` `(height < max_height) {`     `          ``// Increment the ans by` `          ``// (max_height-height)` `          ``ans = ans + (max_height - height);` `        ``}`   `        ``// Define a new node` `        ``node temp = ``new` `node();` `        ``temp.x = new_x;` `        ``temp.y = new_y;` `        ``temp.height = height;`     `        ``// Push the current node` `        ``// in the pq` `        ``pq.offer(temp);`   `        ``// Mark the current cell` `        ``// as visited` `        ``visited[new_x][new_y] = ``true``;` `      ``}` `    ``}`   `    ``return` `ans;` `  ``}`   `  ``// Driver code` `  ``public` `static` `void` `main(String[] args) {` `    ``int``[][] arr = { { ``1``, ``4``, ``3``, ``1``, ``3``, ``2` `}, { ``3``, ``2``, ``1``, ``3``, ``2``, ``4` `}, { ``2``, ``3``, ``3``, ``2``, ``3``, ``1` `} };` `    ``System.out.println(trapRainWater(arr));` `  ``}` `}`   `// This code is contributed by codebraxnzt`

## Python3

 `# Python Code`   `# Stores the direction of all the` `# adjacent cells` `dir` `=` `[[``-``1``, ``0``], [``0``, ``1``], [``1``, ``0``], [``0``, ``-``1``]]`   `# Node structure` `class` `Node:` `    ``def` `__init__(``self``, height, x, y):` `        ``self``.height ``=` `height` `        ``self``.x ``=` `x` `        ``self``.y ``=` `y`   `# Comparator function to implement` `# the min heap using priority queue` `class` `Compare:` `    ``# Comparator function` `    ``def` `__lt__(``self``, a, b):` `        ``return` `a.height > b.height`   `# Function to find the amount of water` `# the matrix is capable to hold` `def` `trapRainWater(heightMap):` `    ``M ``=` `len``(heightMap)` `    ``N ``=` `len``(heightMap[``0``])`   `    ``# Stores if a cell of the matrix` `    ``# is visited or not` `    ``visited ``=` `[[``False` `for` `_ ``in` `range``(N)] ``for` `_ ``in` `range``(M)]`   `    ``# Initialize a priority queue` `    ``pq ``=` `[]`   `    ``# Traverse over the matrix` `    ``for` `i ``in` `range``(M):` `        ``for` `j ``in` `range``(N):`   `            ``# If element is not on` `            ``# the boundary` `            ``if` `i ``=``=` `0` `or` `j ``=``=` `0` `or` `i ``=``=` `M ``-` `1` `or` `j ``=``=` `N ``-` `1``:` `                ``visited[i][j] ``=` `True`   `                ``# Node for priority queue` `                ``t ``=` `Node(heightMap[i][j], i, j)`   `                ``# Pushe all the adjacent` `                ``# node in the pq` `                ``pq.append(t)`   `    ``# Stores the total volume` `    ``ans ``=` `0`   `    ``# Stores the maximum height` `    ``max_height ``=` `float``(``'-inf'``)`   `    ``# Iterate while pq is not empty` `    ``while` `pq:`   `        ``# Store the top node of pq` `        ``front ``=` `pq.pop()`   `        ``# Update the max_height` `        ``max_height ``=` `max``(max_height, front.height)`   `        ``# Stores the position of the` `        ``# current cell` `        ``curr_x ``=` `front.x` `        ``curr_y ``=` `front.y`   `        ``for` `i ``in` `range``(``4``):`   `            ``new_x ``=` `curr_x ``+` `dir``[i][``0``]` `            ``new_y ``=` `curr_y ``+` `dir``[i][``1``]`   `            ``# If adjacent cells are out` `            ``# of bound or already visited` `            ``if` `new_x < ``0` `or` `new_y < ``0` `or` `new_x >``=` `M ``or` `new_y >``=` `N ``or` `visited[new_x][new_y]:` `                ``continue`   `            ``# Stores the height of the` `            ``# adjacent cell` `            ``height ``=` `heightMap[new_x][new_y]`   `            ``# If height of current cell` `            ``# is smaller than max_height` `            ``if` `height < max_height:`   `                ``# Increment the ans by` `                ``# (max_height-height)` `                ``ans ``+``=` `(max_height ``-` `height)`   `            ``# Define a new node` `            ``temp ``=` `Node(height, new_x, new_y)`   `            ``# Push the current node` `            ``# in the pq` `            ``pq.append(temp)`   `            ``# Mark the current cell` `            ``# as visited` `            ``visited[new_x][new_y] ``=` `True`   `    ``return` `ans`   `# Driver Code` `arr ``=` `[[``1``, ``4``, ``3``, ``1``, ``3``, ``2``], [``3``, ``2``, ``1``, ``3``, ``2``, ``4``], [``2``, ``3``, ``3``, ``2``, ``3``, ``1``]]` `print``(trapRainWater(arr))`

## C#

 `using` `System;` `using` `System.Collections.Generic;`   `class` `Gfg` `{` `  ``// Stores the direction of all the` `  ``// adjacent cells` `  ``static` `int``[] dx = { -1, 0, 1, 0 };` `  ``static` `int``[] dy = { 0, 1, 0, -1 };`   `  ``static` `int` `TrapRainWater(``int``[][] heightMap)` `  ``{` `    ``int` `M = heightMap.Length;` `    ``int` `N = heightMap.Length;`   `    ``var` `visited = ``new` `bool``[M, N];`   `    ``// Initialize a sorted set` `    ``var` `pq = ``new` `SortedSet<(``int``, ``int``, ``int``)>();`   `    ``// Traverse over the matrix` `    ``for` `(``int` `i = 0; i < M; i++)` `    ``{` `      ``for` `(``int` `j = 0; j < N; j++)` `      ``{` `        ``// If element is not on the boundary` `        ``if` `(!(i == 0 || j == 0 || i == M - 1 || j == N - 1))` `          ``continue``;`   `        ``// Mark the current cell as visited` `        ``visited[i, j] = ``true``;`   `        ``// Tuple for sorted set` `        ``var` `t = (heightMap[i][j], i, j);`   `        ``// Pushe all the adjacent nodes in the pq` `        ``pq.Add(t);` `      ``}` `    ``}`   `    ``// Stores the total volume` `    ``int` `ans = 0;`   `    ``// Stores the maximum height` `    ``int` `maxHeight = ``int``.MinValue;`   `    ``// Iterate while pq is not empty` `    ``while` `(pq.Count > 0)` `    ``{` `      ``// Store the top node of pq` `      ``var` `front = pq.Min;`   `      ``// Delete the top element of pq` `      ``pq.Remove(front);`   `      ``// Update the maxHeight` `      ``maxHeight = Math.Max(maxHeight, front.Item1);`   `      ``// Stores the position of the current cell` `      ``int` `curr_x = front.Item2;` `      ``int` `curr_y = front.Item3;`   `      ``for` `(``int` `i = 0; i < 4; i++)` `      ``{` `        ``int` `new_x = curr_x + dx[i];` `        ``int` `new_y = curr_y + dy[i];`   `        ``// If adjacent cells are out of bound or already visited` `        ``if` `(new_x < 0 || new_y < 0 || new_x >= M || new_y >= N || visited[new_x, new_y])` `          ``continue``;`   `        ``// Stores the height of the adjacent cell` `        ``int` `height = heightMap[new_x][new_y];`   `        ``// If height of current cell is smaller than maxHeight` `        ``if` `(height < maxHeight)` `        ``{` `          ``// Increment the ans by (maxHeight - height)` `          ``ans = ans + (maxHeight - height);` `        ``}`   `        ``// Tuple for sorted set` `        ``var` `temp = (height, new_x, new_y);`   `        ``// Push the current node in the pq` `        ``pq.Add(temp);`   `        ``// Mark the current cell as visited` `        ``visited[new_x, new_y] = ``true``;` `      ``}` `    ``}`   `    ``return` `ans;` `  ``}`   `  ``static` `void` `Main(``string``[] args)` `  ``{` `    ``int``[][] arr = ``new` `int``[];` `    ``arr = ``new` `int``[] { 1, 4, 3, 1, 3, 2 };` `    ``arr = ``new` `int``[] { 3, 2, 1, 3, 2, 4 };` `    ``arr = ``new` `int``[] { 2, 3, 3, 2, 3, 1 };`   `    ``Console.WriteLine(TrapRainWater(arr));` `  ``}` `}`

## Javascript

 `// Define directions array` `const dir = [[-1, 0], [0, 1], [1, 0], [0, -1]];`   `// Node structure` `class Node {` `  ``constructor(height, x, y) {` `    ``this``.height = height;` `    ``this``.x = x;` `    ``this``.y = y;` `  ``}` `}`   `// Comparator function to implement` `// the min heap using priority queue` `class Compare {` `  ``// Comparator function` `  ``static compare(a, b) {` `    ``return` `a.height > b.height;` `  ``}` `}`   `// Function to find the amount of water` `// the matrix is capable to hold` `function` `trapRainWater(heightMap) {` `  ``const M = heightMap.length;` `  ``const N = heightMap.length;`   `  ``// Stores if a cell of the matrix` `  ``// is visited or not` `  ``const visited = ``new` `Array(M).fill(``false``).map(() => ``new` `Array(N).fill(``false``));`   `  ``// Initialize a priority queue` `  ``const pq = [];`   `  ``// Traverse over the matrix` `  ``for` `(let i = 0; i < M; i++) {` `    ``for` `(let j = 0; j < N; j++) {` `      ``// If element is not on` `      ``// the boundary` `      ``if` `(i === 0 || j === 0 || i === M - 1 || j === N - 1) {` `        ``visited[i][j] = ``true``;`   `        ``// Node for priority queue` `        ``const t = ``new` `Node(heightMap[i][j], i, j);`   `        ``// Push all the adjacent` `        ``// node in the pq` `        ``pq.push(t);` `      ``}` `    ``}` `  ``}`   `  ``// Stores the total volume` `  ``let ans = 0;`   `  ``// Stores the maximum height` `  ``let max_height = -Infinity;`   `  ``// Iterate while pq is not empty` `  ``while` `(pq.length) {` `    ``// Store the top node of pq` `    ``const front = pq.pop();`   `    ``// Update the max_height` `    ``max_height = Math.max(max_height, front.height);`   `    ``// Stores the position of the` `    ``// current cell` `    ``const curr_x = front.x;` `    ``const curr_y = front.y;`   `    ``for` `(let i = 0; i < 4; i++) {` `      ``const new_x = curr_x + dir[i];` `      ``const new_y = curr_y + dir[i];`   `      ``// If adjacent cells are out` `      ``// of bound or already visited` `      ``if` `(new_x < 0 || new_y < 0 || new_x >= M || new_y >= N || visited[new_x][new_y]) {` `        ``continue``;` `      ``}`   `      ``// Stores the height of the` `      ``// adjacent cell` `      ``const height = heightMap[new_x][new_y];`   `      ``// If height of current cell` `      ``// is smaller than max_height` `      ``if` `(height < max_height) {` `        ``// Increment the ans by` `        ``// (max_height-height)` `        ``ans += (max_height - height);` `      ``}`   `      ``// Define a new node` `      ``const temp = ``new` `Node(height, new_x, new_y);`   `      ``// Push the current node` `      ``// in the pq` `      ``pq.push(temp);`   `      ``// Mark the current cell` `      ``// as visited` `      ``visited[new_x][new_y] = ``true``;` `    ``}` `  ``}`   `  ``return` `ans;` `}`   `// Driver Code` `const arr = [[1, 4, 3, 1, 3, 2], [3, 2, 1, 3, 2, 4], [2, 3, 3, 2, 3, 1]];` `console.log(trapRainWater(arr))`

Output

`4`

Time Complexity: (N * M * log(N * M))
Auxiliary Space: O(N * M)

My Personal Notes arrow_drop_up