# 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[0].size();       // Stores if a cell of the matrix     // is visited or not     vector > visited(M,                                   vector(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][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;             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[0].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[3][];     arr[0] = new int[] { 1, 4, 3, 1, 3, 2 };     arr[1] = new int[] { 3, 2, 1, 3, 2, 4 };     arr[2] = 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[0].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][0];       const 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       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)

Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Previous
Next