Check if a path exists for a cell valued 1 to reach the bottom right corner of a Matrix before any cell valued 2


Problems involving grids and matrices are mostly solved using either BFS or DFS traversal algorithms. Taking a look into the first one,

Breadth First Traversal − BFS or Breadth First Traversal is an algorithm for searching a tree or a graph data structure. It starts at the root node and explores all the nodes at the present level before moving on to the next level.

Algorithm

procedure BFS(G, root) is
   let Q be a queue
   label root as explored
   Q.enqueue(root)
   while Q is not empty do
      v := Q.dequeue()
      if v is the goal then
         return v
      for all edges from v to w in G.adjacentEdges(v) do
         if w is not labelled as explored then
            label w as explored
            w.parent := v
            Q.enqueue(w)

Problem Statement

Given a matrix arr[][] having only 0, 1 and 2. The task is to find if 1 can reach the bottom right corner of the matrix before 2.

Constraints

  • Multiple 2’s can be present in the matrix but only 1 is present.

  • Both 1’s and 2’s can move in any of the four directions, i.e. up down left and right but can only move to a cell occupied by 0.

Sample Example 1

Input

arr[][] = 
{{0, 2, 0},
{0, 2, 0},
{0, 1, 0}}

Output

True

Explanation

1 can reach the bottom right corner in 1 move(R) and 2 reaches in 2 moves(RD). So, 1 reaches the bottom right corner before 2.

Sample Example 2

Input

arr[][] = 
{{0, 2, 0},
{0, 1, 0},
{0, 2, 0}}

Output

False

Explanation

2 can reach the bottom right corner in 1 move(R) and 1 reaches in 2 moves(RD). So, 2 reaches the bottom right corner before 1.

Solution Approach: Breadth First Search Traversal

Using the dequeue data structure, we apply BFS to the matrix to find if 1 reaches the bottom right corner before 2. In the dequeue, push 1 in the front and 2 to the back so that if 1 and 2 reach at the same time, 1 is given priority. Then pop elements from the dequeue and see if it is possible to reach the bottom right corner.

Pseudocode

function oneTwo(arr: 2D array of integers):
   n := number of rows of arr
   m := number of columns of arr
   q := empty deque of vectors of integers
    
   for i from 0 to n-1:
      for j from 0 to m-1:
         if arr[i][j] is 1:
            push {i, j, 1} to front of q
         else if arr[i][j] is 2:
            push {i, j, 2} to back of q
         set arr[i][j] to 0
      
   del_x := [0, 1, 0, -1]
   del_y := [-1, 0, 1, 0]
   while q is not empty:
      front := q.front()
      pop front element from q
      i := front[0]
      j := front[1]
      num := front[2]        
      if arr[i][j] is not 0:
         continue        
      set arr[i][j] to 1        
      if num is 1 and (i is n-1 and j is m-1):
         return True
      for d from 0 to 3:
         neighbour_i := i + del_x[d]
         neighbour_j := j + del_y[d]
         if neighbour_i is between 0 and n-1 and neighbour_j is between 0 and m-1:
            push {neighbour_i, neighbour_j, num} to back of q
   return False

Example: C++ Implementation

The following program uses the BFS traversal algorithm.

#include <bits/stdc++.h>
using namespace std;

// Function to find if 1 reaches bottom right corner before 2
bool oneTwo(vector<vector<int>> &arr){
   int n = arr.size();
   int m = arr[0].size();
   deque<vector<int>> q;
   // Adding 1 to front of queue and 2 to back of queue
   for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
         if (arr[i][j] == 1) {
            q.push_front({i, j, 1});
         } else if (arr[i][j] == 2) {
            q.push_back({i, j, 2});
         }
         arr[i][j] = 0;
      }
   }

   int del_x[] = {0, 1, 0, -1};
   int del_y[] = {-1, 0, 1, 0};

   while (!q.empty()) {
      auto front = q.front();
      q.pop_front();
      int i = front[0], j = front[1], num = front[2];
      if (arr[i][j]) {
         continue;
      }
      arr[i][j] = 1;
      // Checking if 1 reached the bottom right corner first
      if (num == 1 and (i == n - 1 && j == m - 1)) {
         return true;
      }
      for (int d = 0; d < 4; d++) {
         int neighbour_i = i + del_x[d];
         int neighbour_j = j + del_y[d];
         if (neighbour_i >= 0 and neighbour_i < n and neighbour_j >= 0 and neighbour_j < m) {
            q.push_back({neighbour_i, neighbour_j, num});
         }
      }
   }
   return false;
}
int main(){
   vector<vector<int>> arr{{0, 2, 0},
      {0, 2, 0},
      {0, 1, 0}};
   if (oneTwo(arr)){
      cout << "True";
   } else {
      cout << "False";
   }
   return 0;
}

Output

True

Time Complexity − O(N*M) where N*M is the dimension of the matrix. This is the time complexity as we traverse through all the elements in the matrix.

Space Complexity − O(N*M) where N*M is the dimension of the matrix. This is the space complexity as dequeue stores all possible directions of the matrix.

Conclusion

In conclusion, the provided solution uses a multi-source BFS and uses a dequeue data structure to prioritise reaching 1 over 2. The time and space complexity of the solution is O(N*M) where N*M are the dimensions of the matrix.

Updated on: 25-Oct-2023

78 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements