Atlantic pacific water flow (original) (raw)

There is an N x M rectangular island that borders both the Pacific Ocean and the Atlantic Ocean. The Pacific Ocean touches the island's left and top edges, and the Atlantic Ocean touches the island's right and bottom edges.

The island is partitioned into a grid of square cells. The island receives a lot of rain, and the rainwater can flow to neighboring cells directly north, south, east, and west if the neighboring cell's height is less than or equal to the current cell's height. Water can flow from any cell adjacent to an ocean into the ocean.

Given a matrix mat[][] having N rows and M columns where mat[x][y] represents the height above sea level of the cell at coordinate (x, y), the task is to find the number of coordinates (x, y) such that the rainwater can flow from the cell (x, y) to both the Pacific and Atlantic oceans.

Example:

Input: mat[][] = {{1, 2, 2, 3, 5},
{3, 2, 3, 4, 4},
{2, 4, 5, 3, 1},
{6, 7, 1, 4, 5},
{5, 1, 1, 2, 4}}

Output: 7
Explanation: In the given matrix, there are 7 coordinates through which the water can flow to both the lakes. They are (0, 4), (1, 3), (1, 4), (2, 2), (3, 0), (3, 1), and (4, 0)

Input: mat[][] = {{2, 2},
{2, 2}}
Output: 4
Example: In the following example, all cells allow water to flow to both the lakes.

Approach: The given problem can be solved using either a DFS or a BFS traversal. The idea is to mark all the cells that are reachable from the directly connected cells from the Pacific and the Atlantic Oceans separately using either DFS or BFS. The count of cells that are connected through both is the required answer. Below are the steps to follow:

Below is the implementation of the above approach:

C++ `

// C++ Program of the above approach #include <bits/stdc++.h> using namespace std;

int x[5] = { 0, 0, -1, 1 }; int y[5] = { 1, -1, 0, 0 };

// Function to check if coordinate // (i, j) lies inside N x M matrix bool safe(int i, int j, int N, int M) { if (i < 0 || j < 0 || i >= N || j >= M) return false; return true; }

// Function to perform a BFS // Traversal and mark visited void BFS(vector<vector > matrix, int N, int M, queue<pair<int, int> > q, vector<vector >& vis) { // Loop to traverse q while (q.empty() == false) { // Stores current coordinate pair<int, int> cur = q.front(); q.pop();

    // Mark current visited
    vis[cur.first][cur.second] = true;
    for (int i = 0; i < 4; i++) {
        int nx = cur.first + x[i];
        int ny = cur.second + y[i];

        // If coordinate (nx, ny)
        // is inbound and rechable
        if (safe(nx, ny, N, M)
            && matrix[nx][ny]
                   >= matrix[cur.first]
                            [cur.second]
            && vis[nx][ny] == false) {
            // Insert into queue
            q.push({ nx, ny });

            // Mark visited
            vis[nx][ny] = true;
        }
    }
}

}

// Function to find the count of // valid coordinates int countCoordinates(vector<vector > mat, int N, int M) { // Queue to perform BFS queue<pair<int, int> > q1, q2;

// Stores the visited coordinates
// during the 1st traversal
vector<vector<bool> > visited1(
    N,
    vector<bool>(M, false));

// Stores the visited coordinates
// during the 2nd traversal
vector<vector<bool> > visited2(
    N,
    vector<bool>(M, false));

// Insert the coordinates
// directly connected
for (int i = 0; i < M; i++) {
    q1.push({ 0, i });
    q2.push({ N - 1, i });
}
for (int j = 0; j < N - 1; j++) {
    q1.push({ j + 1, 0 });
    q2.push({ j, M - 1 });
}

// BFS for the 1st ocean
BFS(mat, N, M, q1, visited1);

// BFS for the 2nd ocean
BFS(mat, N, M, q2, visited2);

// Stores the required count
int ans = 0;

for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        // If coordinate (i, j)
        // is reachable from both
        if (visited1[i][j]
            && visited2[i][j]) {
            // Update count
            ans++;
        }
    }
}

// Return Answer
return ans;

}

// Driver code int main() { vector<vector > mat = { { 1, 2, 2, 3, 5 }, { 3, 2, 3, 4, 4 }, { 2, 4, 5, 3, 1 }, { 6, 7, 1, 4, 5 }, { 5, 1, 1, 2, 4 } };

cout << countCoordinates(mat, mat.size(),
                         mat[0].size());
return 0;

}

Java

// Java Program of the above approach

import java.util.*;

class GFG{

static int x[] = { 0, 0, -1, 1 }; static int y[] = { 1, -1, 0, 0 }; static class pair { int first, second; public pair(int first, int second)
{ this.first = first; this.second = second; }
} // Function to check if coordinate // (i, j) lies inside N x M matrix static boolean safe(int i, int j, int N, int M) { if (i < 0 || j < 0 || i >= N || j >= M) return false; return true; }

// Function to perform a BFS // Traversal and mark visited static void BFS(int[][] matrix, int N, int M, Queue q, boolean [][]vis) { // Loop to traverse q while (q.isEmpty() == false) { // Stores current coordinate pair cur = q.peek(); q.remove();

    // Mark current visited
    vis[cur.first][cur.second] = true;
    for (int i = 0; i < 4; i++) {
        int nx = cur.first + x[i];
        int ny = cur.second + y[i];

        // If coordinate (nx, ny)
        // is inbound and rechable
        if (safe(nx, ny, N, M)
            && matrix[nx][ny]
                   >= matrix[cur.first]
                            [cur.second]
            && vis[nx][ny] == false) {
            // Insert into queue
            q.add(new pair( nx, ny ));

            // Mark visited
            vis[nx][ny] = true;
        }
    }
}

}

// Function to find the count of // valid coordinates static int countCoordinates(int[][] mat, int N, int M) { // Queue to perform BFS Queue q1 =new LinkedList<>(); Queue q2 =new LinkedList<>();

// Stores the visited coordinates
// during the 1st traversal

boolean visited1[][] = new boolean[N][M];
// Stores the visited coordinates
// during the 2nd traversal
boolean visited2[][] = new boolean[N][M];

// Insert the coordinates
// directly connected
for (int i = 0; i < M; i++) {
    q1.add(new pair( 0, i ));
    q2.add(new pair( N - 1, i ));
}
for (int j = 0; j < N - 1; j++) {
    q1.add(new pair( j + 1, 0 ));
    q2.add(new pair( j, M - 1 ));
}

// BFS for the 1st ocean
BFS(mat, N, M, q1, visited1);

// BFS for the 2nd ocean
BFS(mat, N, M, q2, visited2);

// Stores the required count
int ans = 0;

for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        // If coordinate (i, j)
        // is reachable from both
        if (visited1[i][j]
            && visited2[i][j]) {
            // Update count
            ans++;
        }
    }
}

// Return Answer
return ans;

}

// Driver code public static void main(String[] args) { int[][] mat = { { 1, 2, 2, 3, 5 }, { 3, 2, 3, 4, 4 }, { 2, 4, 5, 3, 1 }, { 6, 7, 1, 4, 5 }, { 5, 1, 1, 2, 4 } };

System.out.print(countCoordinates(mat, mat[0].length,
                         mat[1].length));

} }

// This code contributed by shikhasingrajput

Python3

Steps = [
[-1,0], # Up [0,1], # Right [1,0], # bottom [0,-1] # Left ]

def withinLimits(row_num, col_num, total_rows, total_cols): if 0 <= row_num < total_rows and 0 <= col_num < total_cols: return True return False

def waterSlope(oceanMatrix, matrix, row, col): nrows, ncols = len(matrix), len(matrix[0]) for i in Steps: if withinLimits(row+i[0], col+i[1], nrows, ncols): if matrix[row+i[0]][col+i[1]] >= matrix[row][col] and not oceanMatrix[row+i[0]][col+i[1]]: oceanMatrix[row+i[0]][col+i[1]] = True waterSlope(oceanMatrix, matrix, row+i[0], col+i[1])

def commonWaterFlow(matrix): matrix_rows = len(matrix) matrix_cols = len(matrix[0]) pacificMatrix = [[False for _ in range(matrix_cols)] for _ in range(matrix_rows)] atlanticMatrix = [[False for _ in range(matrix_cols)] for _ in range(matrix_rows)]

pacificMatrix[0][1] = True
pacificMatrix[0][2] = True

for i in range(matrix_cols):
    pacificMatrix[0][i] = True
    atlanticMatrix[(matrix_rows-1)][i] = True

for i in range(matrix_rows):
    pacificMatrix[i][0] = True
    atlanticMatrix[i][(matrix_cols-1)] = True

for i in range(matrix_cols):
    waterSlope(pacificMatrix, matrix, 0, i)
    waterSlope(atlanticMatrix, matrix, matrix_rows-1, i)

for i in range(matrix_rows):
    waterSlope(pacificMatrix, matrix, i, 0)
    waterSlope(atlanticMatrix, matrix, i, matrix_cols-1)

Count = 0

for i in range(matrix_rows):
    for j in range(matrix_cols):
        if pacificMatrix[i][j] and atlanticMatrix[i][j]:
            Count += 1

return Count

mat = [ [ 1, 2, 2, 3, 5 ], # T-T-T-T-T F-F-F-F-T [ 3, 2, 3, 4, 4 ], # T-T-T-T-T F-F-F-T-T [ 2, 4, 5, 3, 1 ], # T-T-T-F-F F-F-T-T-T [ 6, 7, 1, 4, 5 ], # T-T-F-F-F T-T-T-T-T [ 5, 1, 1, 2, 4 ] ] # T-F-F-F-F T-T-T-T-T print(commonWaterFlow(mat))

C#

// C# Program of the above approach using System; using System.Collections.Generic;

public class GFG{

static int []x = { 0, 0, -1, 1 }; static int []y = { 1, -1, 0, 0 }; class pair { public int first, second; public pair(int first, int second)
{ this.first = first; this.second = second; }
} // Function to check if coordinate // (i, j) lies inside N x M matrix static bool safe(int i, int j, int N, int M) { if (i < 0 || j < 0 || i >= N || j >= M) return false; return true; }

// Function to perform a BFS // Traversal and mark visited static void BFS(int[,] matrix, int N, int M, Queue q, bool [,]vis) { // Loop to traverse q while (q.Count!=0 ) { // Stores current coordinate pair cur = q.Peek(); q.Dequeue();

    // Mark current visited
    vis[cur.first,cur.second] = true;
    for (int i = 0; i < 4; i++) {
        int nx = cur.first + x[i];
        int ny = cur.second + y[i];

        // If coordinate (nx, ny) 
        // is inbound and rechable
        if (safe(nx, ny, N, M)
            && matrix[nx,ny]
                   >= matrix[cur.first,cur.second]
            && vis[nx,ny] == false) {
            // Insert into queue
            q.Enqueue(new pair( nx, ny ));

            // Mark visited
            vis[nx,ny] = true;
        }
    }
}

}

// Function to find the count of // valid coordinates static int countCoordinates(int[,] mat, int N, int M) { // Queue to perform BFS Queue q1 =new Queue(); Queue q2 =new Queue();

// Stores the visited coordinates
// during the 1st traversal

bool [,]visited1 = new bool[N,M];
// Stores the visited coordinates
// during the 2nd traversal
bool [,]visited2 = new bool[N,M];

// Insert the coordinates
// directly connected
for (int i = 0; i < M; i++) {
    q1.Enqueue(new pair( 0, i ));
    q2.Enqueue(new pair( N - 1, i ));
}
for (int j = 0; j < N - 1; j++) {
    q1.Enqueue(new pair( j + 1, 0 ));
    q2.Enqueue(new pair( j, M - 1 ));
}

// BFS for the 1st ocean
BFS(mat, N, M, q1, visited1);

// BFS for the 2nd ocean
BFS(mat, N, M, q2, visited2);

// Stores the required count
int ans = 0;

for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        // If coordinate (i, j)
        // is reachable from both
        if (visited1[i,j]
            && visited2[i,j]) {
            // Update count
            ans++;
        }
    }
}

// Return Answer
return ans;

}

// Driver code public static void Main(String[] args) { int[,] mat = { { 1, 2, 2, 3, 5 }, { 3, 2, 3, 4, 4 }, { 2, 4, 5, 3, 1 }, { 6, 7, 1, 4, 5 }, { 5, 1, 1, 2, 4 } };

Console.Write(countCoordinates(mat, mat.GetLength(0),
                         mat.GetLength(1))); 

} }

// This code contributed by shikhasingrajput

JavaScript

const Steps = [ [-1, 0], // Up [0, 1], // Right [1, 0], // Bottom [0, -1] // Left ];

function withinLimits(row_num, col_num, total_rows, total_cols) { return row_num >= 0 && row_num < total_rows && col_num >= 0 && col_num < total_cols; }

function waterSlope(oceanMatrix, matrix, row, col) { const nrows = matrix.length, ncols = matrix[0].length; for (const [r, c] of Steps) { if (withinLimits(row+r, col+c, nrows, ncols)) { if (matrix[row+r][col+c] >= matrix[row][col] && !oceanMatrix[row+r][col+c]) { oceanMatrix[row+r][col+c] = true; waterSlope(oceanMatrix, matrix, row+r, col+c); } } } }

function commonWaterFlow(matrix) { const matrix_rows = matrix.length, matrix_cols = matrix[0].length; const pacificMatrix = Array.from({length: matrix_rows}, () => Array(matrix_cols).fill(false)); const atlanticMatrix = Array.from({length: matrix_rows}, () => Array(matrix_cols).fill(false));

pacificMatrix[0][1] = true; pacificMatrix[0][2] = true;

for (let i = 0; i < matrix_cols; i++) { pacificMatrix[0][i] = true; atlanticMatrix[(matrix_rows-1)][i] = true; }

for (let i = 0; i < matrix_rows; i++) { pacificMatrix[i][0] = true; atlanticMatrix[i][(matrix_cols-1)] = true; }

for (let i = 0; i < matrix_cols; i++) { waterSlope(pacificMatrix, matrix, 0, i); waterSlope(atlanticMatrix, matrix, matrix_rows-1, i); }

for (let i = 0; i < matrix_rows; i++) { waterSlope(pacificMatrix, matrix, i, 0); waterSlope(atlanticMatrix, matrix, i, matrix_cols-1); }

let Count = 0;

for (let i = 0; i < matrix_rows; i++) { for (let j = 0; j < matrix_cols; j++) { if (pacificMatrix[i][j] && atlanticMatrix[i][j]) { Count++; } } }

return Count; }

const mat = [ [1, 2, 2, 3, 5], // T-T-T-T-T F-F-F-F-T [3, 2, 3, 4, 4], // T-T-T-T-T F-F-F-T-T [2, 4, 5, 3, 1], // T-T-T-F-F F-F-T-T-T [6, 7, 1, 4, 5], // T-T-F-F-F T-T-T-T-T [5, 1, 1, 2, 4] // T-F-F-F-F T-T-T-T-T ]; console.log(commonWaterFlow(mat)); // This code is contributed by Prince Kumar

`

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