Given a binary matrix mat[][] of size n × m containing values 0 and 1, and a source cell src[] and destination cell dest[], find the minimum number of steps required to reach the destination cell from the source cell. From any cell, you can move to its adjacent cells in the up, down, left, and right directions.
1 represents a traversable cell.
0 represents a blocked cell that cannot be visited.
If the destination cannot be reached from the source, return -1.
Example:
Input: mat[][] = {{1, 1, 1, 1},{1, 1, 0, 1},{1, 1, 1, 1},{1, 1, 0, 0},{1, 0, 0, 1}}, src[] = {0, 1}, dest[] = {2, 2} Output: 3 Explanation: From (0,1), the minimum number of steps to reach (2,2) is 3,
Input: mat[][] = {{1, 1, 1, 1, 1},{1, 1, 1, 1, 1},{1, 1, 1, 1, 0},{1, 0, 1, 0, 1}}, src[] = {0, 0}, dest[] = {3, 4} Output:-1 Explanation: From (0,0), the destination (3,4) cannot be reached because all possible paths are blocked by 0 cells, so no valid route exists.
[Naive Approach] Using DFS - O(4^n*m) Time and O(m × n) Space
The idea is to start from the source cell and recursively explore all possible paths to reach the destination cell in the binary matrix. From any cell, we can move in four possible directions: up, down, left, and right, as long as the next cell is valid (inside the grid, not blocked, and not already visited in the current path).
We maintain a visited matrix to avoid cycles and ensure we do not revisit the same cell in a single path. A global variable minDist is used to store the minimum distance found across all possible paths.
Base Cases:
If the current cell (x, y) is equal to the destination cell (dx, dy), we update minDist with the minimum of the current distance and return.
If the current cell is out of bounds or blocked or already visited, we stop exploring that path.
The recurrence relation will be: dfs(x, y) = dfs(x+1, y) + dfs(x-1, y) + dfs(x, y+1) + dfs(x, y-1)
C++
#include<iostream>#include<vector>#include<climits>usingnamespacestd;// Stores the minimum distance found from source to destinationintminDist=INT_MAX;// Function to check if a cell is safe to visitboolisSafe(vector<vector<int>>&mat,vector<vector<bool>>&vis,intx,inty){intn=mat.size();intm=mat[0].size();// Check boundary conditions, cell value, and whether already visitedreturn(x>=0&&x<n&&y>=0&&y<m&&mat[x][y]==1&&!vis[x][y]);}// DFS function to explore all possible pathsvoiddfs(vector<vector<int>>&mat,vector<vector<bool>>&vis,intx,inty,intdx,intdy,intdist){// If destination is reached, update minimum distanceif(x==dx&&y==dy){minDist=min(minDist,dist);return;}// Mark current cell as visitedvis[x][y]=true;// Possible movements: Up, Down, Left, RightintdirX[]={-1,1,0,0};intdirY[]={0,0,-1,1};// Try all 4 directionsfor(inti=0;i<4;i++){intnx=x+dirX[i];intny=y+dirY[i];// If next move is valid, continue DFSif(isSafe(mat,vis,nx,ny)){dfs(mat,vis,nx,ny,dx,dy,dist+1);}}// Backtrack: unmark the cell so other paths can use itvis[x][y]=false;}// Wrapper function to calculate shortest pathintshortestPath(vector<vector<int>>&mat,vector<int>&src,vector<int>&dest){intn=mat.size();intm=mat[0].size();// If source or destination is blocked, return -1if(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;// Visited matrix to avoid cyclesvector<vector<bool>>vis(n,vector<bool>(m,false));// Initialize minimum distanceminDist=INT_MAX;// Start DFS from source celldfs(mat,vis,src[0],src[1],dest[0],dest[1],0);// If no path found, return -1return(minDist==INT_MAX)?-1:minDist;}intmain(){vector<vector<int>>mat={{1,1,1,1},{1,1,0,1},{1,1,1,1},{1,1,0,0},{1,0,0,1}};vector<int>src={0,1};vector<int>dest={2,2};cout<<shortestPath(mat,src,dest);return0;}
Java
importjava.util.*;classSolution{// Stores the minimum distance found from source to destinationstaticintminDist=Integer.MAX_VALUE;// Function to check if a cell is safe to visitstaticbooleanisSafe(int[][]mat,boolean[][]vis,intx,inty){intn=mat.length;intm=mat[0].length;// Check boundary conditions, cell value, and whether already visitedreturn(x>=0&&x<n&&y>=0&&y<m&&mat[x][y]==1&&!vis[x][y]);}// DFS function to explore all possible pathsstaticvoiddfs(int[][]mat,boolean[][]vis,intx,inty,intdx,intdy,intdist){// If destination is reached, update minimum distanceif(x==dx&&y==dy){minDist=Math.min(minDist,dist);return;}// Mark current cell as visitedvis[x][y]=true;// Possible movements: Up, Down, Left, Rightint[]dirX={-1,1,0,0};int[]dirY={0,0,-1,1};// Try all 4 directionsfor(inti=0;i<4;i++){intnx=x+dirX[i];intny=y+dirY[i];// If next move is valid, continue DFSif(isSafe(mat,vis,nx,ny)){dfs(mat,vis,nx,ny,dx,dy,dist+1);}}// Backtrack: unmark the cell so other paths can use itvis[x][y]=false;}staticintshortestPath(int[][]mat,int[]src,int[]dest){intn=mat.length;intm=mat[0].length;// If source or destination is blocked, return -1if(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;boolean[][]vis=newboolean[n][m];// Initialize minimum distanceminDist=Integer.MAX_VALUE;// Start DFS from source celldfs(mat,vis,src[0],src[1],dest[0],dest[1],0);// If no path found, return -1return(minDist==Integer.MAX_VALUE)?-1:minDist;}}
Python
# Stores the minimum distance found from source to destinationminDist=float('inf')# Function to check if a cell is safe to visitdefisSafe(mat,vis,x,y):n=len(mat)m=len(mat[0])# Check boundary conditions, cell value, and whether already visitedreturn(0<=x<nand0<=y<mandmat[x][y]==1andnotvis[x][y])# DFS function to explore all possible pathsdefdfs(mat,vis,x,y,dx,dy,dist):globalminDist# If destination is reached, update minimum distanceifx==dxandy==dy:minDist=min(minDist,dist)return# Mark current cell as visitedvis[x][y]=True# Possible movements: Up, Down, Left, RightdirX=[-1,1,0,0]dirY=[0,0,-1,1]# Try all 4 directionsforiinrange(4):nx=x+dirX[i]ny=y+dirY[i]# If next move is valid, continue DFSifisSafe(mat,vis,nx,ny):dfs(mat,vis,nx,ny,dx,dy,dist+1)# Backtrack: unmark the cell so other paths can use itvis[x][y]=False# Wrapper function to calculate shortest pathdefshortestPath(mat,src,dest):globalminDistn=len(mat)m=len(mat[0])# If source or destination is blockedifmat[src[0]][src[1]]==0ormat[dest[0]][dest[1]]==0:return-1# Visited matrixvis=[[Falsefor_inrange(m)]for_inrange(n)]# Initialize minimum distanceminDist=float('inf')# Start DFS from source celldfs(mat,vis,src[0],src[1],dest[0],dest[1],0)# If no path foundreturn-1ifminDist==float('inf')elseminDistif__name__=="__main__":mat=[[1,1,1,1],[1,1,0,1],[1,1,1,1],[1,1,0,0],[1,0,0,1]]src=[0,1]dest=[2,2]print(shortestPath(mat,src,dest))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Stores the minimum distance found from source to destinationstaticintminDist=Int32.MaxValue;// Function to check if a cell is safe to visitstaticboolisSafe(int[][]mat,bool[][]vis,intx,inty){intn=mat.Length;intm=mat[0].Length;// Check boundary conditions, cell value, and whether already visitedreturn(x>=0&&x<n&&y>=0&&y<m&&mat[x][y]==1&&!vis[x][y]);}// DFS function to explore all possible pathsstaticvoiddfs(int[][]mat,bool[][]vis,intx,inty,intdx,intdy,intdist){// If destination is reached, update minimum distanceif(x==dx&&y==dy){minDist=Math.Min(minDist,dist);return;}// Mark current cell as visitedvis[x][y]=true;// Possible movements: Up, Down, Left, Rightint[]dirX={-1,1,0,0};int[]dirY={0,0,-1,1};// Try all 4 directionsfor(inti=0;i<4;i++){intnx=x+dirX[i];intny=y+dirY[i];// If next move is valid, continue DFSif(isSafe(mat,vis,nx,ny)){dfs(mat,vis,nx,ny,dx,dy,dist+1);}}// Backtrack: unmark the cell so other paths can use itvis[x][y]=false;}staticintshortestPath(int[][]mat,int[]src,int[]dest){intn=mat.Length;intm=mat[0].Length;// If source or destination is blockedif(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;bool[][]vis=newbool[n][];for(inti=0;i<n;i++)vis[i]=newbool[m];minDist=Int32.MaxValue;dfs(mat,vis,src[0],src[1],dest[0],dest[1],0);return(minDist==Int32.MaxValue)?-1:minDist;}// MainstaticvoidMain(){int[][]mat=newint[][]{newint[]{1,1,1,1},newint[]{1,1,0,1},newint[]{1,1,1,1},newint[]{1,1,0,0},newint[]{1,0,0,1}};int[]src={0,1};int[]dest={2,2};Console.WriteLine(shortestPath(mat,src,dest));}}
JavaScript
"use strict";// Stores the minimum distance found from source to destinationletminDist=Infinity;// Function to check if a cell is safe to visitfunctionisSafe(mat,vis,x,y){letn=mat.length;letm=mat[0].length;// Check boundary conditions, cell value, and whether already visitedreturn(x>=0&&x<n&&y>=0&&y<m&&mat[x][y]===1&&!vis[x][y]);}// DFS function to explore all possible pathsfunctiondfs(mat,vis,x,y,dx,dy,dist){// If destination is reached, update minimum distanceif(x===dx&&y===dy){minDist=Math.min(minDist,dist);return;}// Mark current cell as visitedvis[x][y]=true;// Possible movements: Up, Down, Left, RightletdirX=[-1,1,0,0];letdirY=[0,0,-1,1];// Try all 4 directionsfor(leti=0;i<4;i++){letnx=x+dirX[i];letny=y+dirY[i];// If next move is valid, continue DFSif(isSafe(mat,vis,nx,ny)){dfs(mat,vis,nx,ny,dx,dy,dist+1);}}// Backtrackvis[x][y]=false;}// Wrapper functionfunctionshortestPath(mat,src,dest){letn=mat.length;letm=mat[0].length;// If source or destination is blockedif(mat[src[0]][src[1]]===0||mat[dest[0]][dest[1]]===0)return-1;letvis=Array.from({length:n},()=>Array(m).fill(false));minDist=Infinity;dfs(mat,vis,src[0],src[1],dest[0],dest[1],0);return(minDist===Infinity)?-1:minDist;}// Driver codeletmat=[[1,1,1,1],[1,1,0,1],[1,1,1,1],[1,1,0,0],[1,0,0,1]];letsrc=[0,1];letdest=[2,2];console.log(shortestPath(mat,src,dest));
Output
3
[Expected Approach] Using BFS - O(n × m) Time and O(n× m) Space
The idea is to use Breadth First Search (BFS) to find the shortest path in the binary matrix. We start from the source cell and explore all reachable cells level by level using a queue.
Each queue element stores the cell coordinates along with the distance from the source. Since BFS explores all nodes at the current distance before moving to the next level, the first time we reach the destination cell, it gives the minimum number of steps.
We mark cells as visited (set them to 0) to avoid revisiting and ensure each cell is processed only once.
Base Cases:
If the source or destination cell is blocked (0), return -1.
If the destination is reached during BFS traversal, return the current distance.
C++
#include<iostream>#include<queue>#include<vector>usingnamespacestd;intshortestPath(vector<vector<int>>&mat,vector<int>&src,vector<int>&dest){intn=mat.size();intm=mat[0].size();// Source or destination is blockedif(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;// Queue stores {cell, distance from source}queue<pair<pair<int,int>,int>>q;q.push({{src[0],src[1]},0});// Mark source as visitedmat[src[0]][src[1]]=0;// Four possible directionsintdx[]={-1,1,0,0};intdy[]={0,0,-1,1};while(!q.empty()){autocurr=q.front();q.pop();intx=curr.first.first;inty=curr.first.second;intdist=curr.second;// Destination reachedif(x==dest[0]&&y==dest[1])returndist;// Explore all four adjacent cellsfor(inti=0;i<4;i++){intnx=x+dx[i];intny=y+dy[i];if(nx>=0&&nx<n&&ny>=0&&ny<m&&mat[nx][ny]==1){// Mark as visitedmat[nx][ny]=0;q.push({{nx,ny},dist+1});}}}// Destination cannot be reachedreturn-1;}intmain(){vector<vector<int>>mat={{1,1,1,1},{1,1,0,1},{1,1,1,1},{1,1,0,0},{1,0,0,1}};vector<int>src={0,1};vector<int>dest={2,2};cout<<shortestPath(mat,src,dest);return0;}
Java
importjava.util.Queue;importjava.util.LinkedList;importjava.util.Arrays;classGFG{intshortestPath(int[][]mat,int[]src,int[]dest){intn=mat.length;intm=mat[0].length;// Source or destination is blockedif(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;// Queue stores {cell, distance from source}Queue<int[]>q=newLinkedList<>();q.add(newint[]{src[0],src[1],0});// Mark source as visitedmat[src[0]][src[1]]=0;// Four possible directionsintdx[]={-1,1,0,0};intdy[]={0,0,-1,1};while(!q.isEmpty()){int[]curr=q.poll();intx=curr[0];inty=curr[1];intdist=curr[2];// Destination reachedif(x==dest[0]&&y==dest[1])returndist;// Explore all four adjacent cellsfor(inti=0;i<4;i++){intnx=x+dx[i];intny=y+dy[i];if(nx>=0&&nx<n&&ny>=0&&ny<m&&mat[nx][ny]==1){// Mark as visitedmat[nx][ny]=0;q.add(newint[]{nx,ny,dist+1});}}}// Destination cannot be reachedreturn-1;}publicstaticvoidmain(String[]args){int[][]mat={{1,1,1,1},{1,1,0,1},{1,1,1,1},{1,1,0,0},{1,0,0,1}};int[]src={0,1};int[]dest={2,2};Solutionobj=newSolution();System.out.println(obj.shortestPath(mat,src,dest));}}
Python
fromcollectionsimportdequedefshortestPath(mat,src,dest):n=len(mat)m=len(mat[0])# Source or destination is blockedifmat[src[0]][src[1]]==0ormat[dest[0]][dest[1]]==0:return-1# Queue stores {cell, distance from source}q=deque()q.append((src[0],src[1],0))# Mark source as visitedmat[src[0]][src[1]]=0# Four possible directionsdx=[-1,1,0,0]dy=[0,0,-1,1]whileq:x,y,dist=q.popleft()# Destination reachedifx==dest[0]andy==dest[1]:returndist# Explore all four adjacent cellsforiinrange(4):nx=x+dx[i]ny=y+dy[i]if0<=nx<nand0<=ny<mandmat[nx][ny]==1:# Mark as visitedmat[nx][ny]=0q.append((nx,ny,dist+1))# Destination cannot be reachedreturn-1if__name__=="__main__":mat=[[1,1,1,1],[1,1,0,1],[1,1,1,1],[1,1,0,0],[1,0,0,1]]src=[0,1]dest=[2,2]print(shortestPath(mat,src,dest))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{publicintshortestPath(int[][]mat,int[]src,int[]dest){intn=mat.Length;intm=mat[0].Length;// Source or destination is blockedif(mat[src[0]][src[1]]==0||mat[dest[0]][dest[1]]==0)return-1;// Queue stores {cell, distance from source}Queue<int[]>q=newQueue<int[]>();q.Enqueue(newint[]{src[0],src[1],0});// Mark source as visitedmat[src[0]][src[1]]=0;// Four possible directionsint[]dx={-1,1,0,0};int[]dy={0,0,-1,1};while(q.Count>0){int[]curr=q.Dequeue();intx=curr[0];inty=curr[1];intdist=curr[2];// Destination reachedif(x==dest[0]&&y==dest[1])returndist;// Explore all four adjacent cellsfor(inti=0;i<4;i++){intnx=x+dx[i];intny=y+dy[i];if(nx>=0&&nx<n&&ny>=0&&ny<m&&mat[nx][ny]==1){// Mark as visitedmat[nx][ny]=0;q.Enqueue(newint[]{nx,ny,dist+1});}}}// Destination cannot be reachedreturn-1;}publicstaticvoidMain(string[]args){int[][]mat=newint[][]{newint[]{1,1,1,1},newint[]{1,1,0,1},newint[]{1,1,1,1},newint[]{1,1,0,0},newint[]{1,0,0,1}};int[]src={0,1};int[]dest={2,2};Solutionobj=newSolution();Console.WriteLine(obj.shortestPath(mat,src,dest));}}
JavaScript
functionshortestPath(mat,src,dest){letn=mat.length;letm=mat[0].length;// Source or destination is blockedif(mat[src[0]][src[1]]===0||mat[dest[0]][dest[1]]===0)return-1;// Queue stores {cell, distance from source}letq=[];q.push([src[0],src[1],0]);// Mark source as visitedmat[src[0]][src[1]]=0;// Four possible directionsletdx=[-1,1,0,0];letdy=[0,0,-1,1];while(q.length>0){letcurr=q.shift();letx=curr[0];lety=curr[1];letdist=curr[2];// Destination reachedif(x===dest[0]&&y===dest[1])returndist;// Explore all four adjacent cellsfor(leti=0;i<4;i++){letnx=x+dx[i];letny=y+dy[i];if(nx>=0&&nx<n&&ny>=0&&ny<m&&mat[nx][ny]===1){// Mark as visitedmat[nx][ny]=0;q.push([nx,ny,dist+1]);}}}// Destination cannot be reachedreturn-1;}// Driver codeletmat=[[1,1,1,1],[1,1,0,1],[1,1,1,1],[1,1,0,0],[1,0,0,1]];letsrc=[0,1];letdest=[2,2];console.log(shortestPath(mat,src,dest));