Given a 2D binary matrix of size N * M, where 0 represents an empty space while 1 represents a wall you cannot walk through. You are also given an integer K. You can walk up, down, left, or right. Given that you can remove up to K walls, return the minimum number of steps to walk from the top left corner (0, 0) to the bottom right corner (N-1, M-1).
Note: If there is no way to walk from the top left corner to the bottom right corner, return -1.
Examples:
Input: N = 3, M = 3, K = 1
mat = {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}}
Output: 4
Explanation: We can remove any one of the walls and reach the bottom in 4 moves.The below image gives the paths through which we can go from the source to the destination.
If we carefully observe the paths shown above then, we will see that in these paths we have one cell that contains 1 and since we have k=1 hence we can traverse this cell also, and hence it gives the minimum steps.
Input: N = 2, M = 2, K = 0
mat[] = {{0, 1}, {1, 0}}
Output: -1
Explanation: There’s no way of reaching the bottom corner without removing any walls.
Approach:
The idea is to use breadth first search to calculate the shortest path from source to destination.
Follow the steps below to solve the problem:
- Initialize a 3D array that ensures that we don’t visit the same cell again and again. Also,Initialize the steps as 0.
- Initialize a queue data structure that contains a list that will be composed of the current_X coordinate, current_Y coordinate, and the no. of obstacles that we can destroy. Push the current cell into the queue.
- Do the following until the queue becomes empty:-
- Pop the front element from the queue and explore this popped cell in all four directions such that the current_X coordinate and current_Y coordinate should not cross the boundary.
- If the current cell is 0 and not visited then explore all the directions. Push all the nonvisited cells from this cell into the queue. Mark this cell as visited.
- If the current cell is 1 which means it represents a wall and this cell is not visited as well as the no of obstacles that we can destroy is greater than 1 which means that we can destroy this wall and then explore all the directions. Push all the nonvisited cells from this cell into the queue. Mark this cell as visited.
- After each iteration increment the step value.
- During the previous two steps, if at any time the current_X coordinate, current_Y coordinate is equal to the destination_X coordinate, destination_Y coordinate then return the steps.
Below is the implementation of the above approach.
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function to find the minimum number of steps int shortestPath(vector<vector< int > > mat, int k) { int n = mat.size(); int m = mat[0].size(); if (n == 1 && m == 1 && (mat[0][0] == 0 || k >= 1)) return 0; vector<vector<vector< bool > > > visited( n, vector<vector< bool > >( m, vector< bool >(k + 1, false ))); int steps = 0; queue<vector< int > > q; q.push({ 0, 0, k }); int ar1[4] = { 1, -1, 0, 0 }; int ar2[4] = { 0, 0, -1, 1 }; // Loop to run a BFS while (!q.empty()) { int size = q.size(); steps++; while (size--) { auto curr = q.front(); int i = curr[0], j = curr[1], w = curr[2]; q.pop(); visited[i][j][w] = true ; for ( int dir = 0; dir < 4; dir++) { int new_x = i + ar1[dir]; int new_y = j + ar2[dir]; int new_k = w; if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m) { if (mat[new_x][new_y] == 0 && !visited[new_x][new_y][new_k]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.push({ new_x, new_y, new_k }); visited[new_x][new_y][new_k] = true ; } else if (mat[new_x][new_y] == 1 && new_k >= 1 && !visited[new_x][new_y] [new_k - 1]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.push({ new_x, new_y, new_k - 1 }); visited[new_x][new_y][new_k - 1] = true ; } } } } } return -1; } // Driver code int main() { vector<vector< int > > mat = { { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 } }; int K = 1; // Function call cout << shortestPath(mat, K); return 0; } |
Java
// Java code to implement the approach import java.io.*; import java.util.*; class GFG { // Function to find the minimum number of steps public static int shortestPath( int [][] mat, int k) { int n = mat.length; int m = mat[ 0 ].length; if (n == 1 && m == 1 && (mat[ 0 ][ 0 ] == 0 || k >= 1 )) return 0 ; boolean [][][] visited = new boolean [n][m][k+ 1 ]; for ( int i= 0 ;i<n;i++) { for ( int j= 0 ;j<m;j++) { for ( int q= 0 ;q<k+ 1 ;q++) { visited[i][j][q]= false ; } } } int steps = 0 ; ArrayList<ArrayList<Integer> > q = new ArrayList<ArrayList<Integer> >(); q.add( new ArrayList<Integer>(Arrays.asList( 0 , 0 , k))); int [] ar1 = { 1 , - 1 , 0 , 0 }; int [] ar2 = { 0 , 0 , - 1 , 1 }; // Loop to run a BFS while (q.size()!= 0 ) { int size = q.size(); steps++; while (size> 0 ) { ArrayList<Integer> curr = q.get( 0 ); int i = curr.get( 0 ), j = curr.get( 1 ), w = curr.get( 2 ); q.remove( 0 ); visited[i][j][w] = true ; for ( int dir = 0 ; dir < 4 ; dir++) { int new_x = i + ar1[dir]; int new_y = j + ar2[dir]; int new_k = w; if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m) { if (mat[new_x][new_y] == 0 && !visited[new_x][new_y][new_k]) { if (new_x == n - 1 && new_y == m - 1 ) return steps; q.add( new ArrayList<Integer>(Arrays.asList(new_x,new_y,new_k))); visited[new_x][new_y][new_k] = true ; } else if (mat[new_x][new_y] == 1 && new_k >= 1 && !visited[new_x][new_y] [new_k - 1 ]) { if (new_x == n - 1 && new_y == m - 1 ) return steps; q.add( new ArrayList<Integer>(Arrays.asList(new_x,new_y,new_k- 1 ))); visited[new_x][new_y][new_k - 1 ] = true ; } } } size--; } } return - 1 ; } public static void main (String[] args) { int [][] mat = { { 0 , 0 , 0 }, { 0 , 0 , 1 }, { 0 , 1 , 0 } }; int K = 1 ; // Function call System.out.println(shortestPath(mat, K)); } } // This code is contributed by Aman Kumar |
Python3
# Python3 code to implement the approach # Function to find the minimum number of steps def shortestPath(mat, k): n = len (mat) m = len (mat[ 0 ]) if (n = = 1 and m = = 1 and (mat[ 0 ][ 0 ] = = 0 or k > = 1 )): return 0 visited = [[[ False for _ in range (k + 1 )] for _ in range (m)] for _ in range (n)] steps = 0 q = [] q.append([ 0 , 0 , k]) ar1 = [ 1 , - 1 , 0 , 0 ] ar2 = [ 0 , 0 , - 1 , 1 ] # Loop to run a BFS while ( len (q) ! = 0 ): size = len (q) steps + = 1 while (size): curr = q.pop( 0 ) i = curr[ 0 ] j = curr[ 1 ] w = curr[ 2 ] visited[i][j][w] = True for dir in range ( 0 , 4 ): new_x = i + ar1[ dir ] new_y = j + ar2[ dir ] new_k = w if (new_x > = 0 and new_x < n and new_y > = 0 and new_y < m): if (mat[new_x][new_y] = = 0 and ( not visited[new_x][new_y][new_k])): if (new_x = = n - 1 and new_y = = m - 1 ): return steps q.append([new_x, new_y, new_k]) visited[new_x][new_y][new_k] = True elif (mat[new_x][new_y] = = 1 and new_k > = 1 and ( not visited[new_x][new_y] [new_k - 1 ])): if (new_x = = n - 1 and new_y = = m - 1 ): return steps q.append([new_x, new_y, new_k - 1 ]) visited[new_x][new_y][new_k - 1 ] = True size - = 1 return - 1 # Driver code if __name__ = = "__main__" : mat = [[ 0 , 0 , 0 ], [ 0 , 0 , 1 ], [ 0 , 1 , 0 ]] K = 1 # Function call print (shortestPath(mat, K)) # This code is contributed by rakeshsahni |
C#
// C# Code to implement the approach using System; using System.Collections.Generic; public class Program { // Function to find the minimum number of steps public static int ShortestPath( int [, ] mat, int k) { int n = mat.GetLength(0); int m = mat.GetLength(1); if (n == 1 && m == 1 && (mat[0, 0] == 0 || k >= 1)) return 0; bool [, , ] visited = new bool [n, m, k + 1]; int steps = 0; Queue< int []> q = new Queue< int []>(); q.Enqueue( new int [] { 0, 0, k }); int [] ar1 = { 1, -1, 0, 0 }; int [] ar2 = { 0, 0, -1, 1 }; // Loop to run a BFS while (q.Count != 0) { int size = q.Count; steps++; while (size-- > 0) { int [] curr = q.Dequeue(); int i = curr[0], j = curr[1], w = curr[2]; visited[i, j, w] = true ; for ( int dir = 0; dir < 4; dir++) { int new_x = i + ar1[dir]; int new_y = j + ar2[dir]; int new_k = w; if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m) { if (mat[new_x, new_y] == 0 && !visited[new_x, new_y, new_k]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.Enqueue( new int [] { new_x, new_y, new_k }); visited[new_x, new_y, new_k] = true ; } else if (mat[new_x, new_y] == 1 && new_k >= 1 && !visited[new_x, new_y, new_k - 1]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.Enqueue( new int [] { new_x, new_y, new_k - 1 }); visited[new_x, new_y, new_k - 1] = true ; } } } } } return -1; } // Driver Code public static void Main() { int [, ] mat = { { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 } }; int K = 1; // Function call Console.WriteLine(ShortestPath(mat, K)); } } // This code is contributed by ishankhandelwals. |
Javascript
// JavaScript code to implement the approach function shotestPath(mat, k) { let n = mat.length; let m = mat[0].length; if (n == 1 && m == 1 && (mat[0][0] == 0 || k >= 1)) return 0; let visited = Array(n).fill().map(() => Array(m).fill().map(() => Array(k + 1).fill( false ))); let steps = 0; let q = []; q.push([0, 0, k]); let ar1 = [1, -1, 0, 0]; let ar2 = [0, 0, -1, 1]; // Loop to run a BFS while (q.length > 0) { let size = q.length; steps++; while (size-- > 0) { let curr = q.shift(); let i = curr[0], j = curr[1], w = curr[2]; visited[i][j][w] = true ; for (let dir = 0; dir < 4; dir++) { let new_x = i + ar1[dir]; let new_y = j + ar2[dir]; let new_k = w; if (new_x >= 0 && new_x < n && new_y >= 0 && new_y < m) { if (mat[new_x][new_y] == 0 && !visited[new_x][new_y][new_k]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.push([new_x, new_y, new_k]); visited[new_x][new_y][new_k] = true ; } else if (mat[new_x][new_y] == 1 && new_k >= 1 && !visited[new_x][new_y] [new_k - 1]) { if (new_x == n - 1 && new_y == m - 1) return steps; q.push([new_x, new_y, new_k - 1]); visited[new_x][new_y][new_k - 1] = true ; } } } } } return -1; } // Driver code let mat = [[0, 0, 0], [0, 0, 1], [0, 1, 0]]; let K = 1; // Function call console.log(shortestPath(mat, K)); // This code is contributed by ishankhandelwals. |
4
Time Complexity: O(N*M*K), For every cell (M*N), in the worst case we have to put that cell into the queue K times.
Space Complexity: O(N*M*K), In the worst case store all of those steps/paths in the visited set.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!