Shortest path in a Matrix from top-left to bottom right-corner with neighbors exceeding at most K
Given a matrix mat[][] and an integer K, the task is to find the length of the shortest path in a matrix from top-left to bottom right corner such that the difference between neighbor nodes does not exceed K.
Example:
Input: mat = {{-1, 0, 4, 3}, K = 4, src = {0, 0}, dest = {2, 3}
{ 6, 5, 7, 8},
{ 2, 1, 2, 0}}
Output: 7
Explanation: The only shortest path where the difference between neighbor nodes does not exceed K is: -1 -> 0 ->4 -> 7 ->5 ->1 ->2 ->0Input: mat = {{-1, 0, 4, 3}, K = 5, src = {0, 0}, dest = {2, 3}
{ 6, 5, 7, 8},
{ 2, 1, 2, 0}}
Output: 5
Approach: The given problem can be solved using breadth-first-search. The idea is to stop exploring the path if the difference between neighbor nodes exceeds K. Below steps can be used to solve the problem:
- Apply breadth-first-search on the source node and visit the neighbor’s nodes whose absolute difference between their values and the current node’s value is not greater than K
- A boolean matrix is used to keep track of visited cells of the matrix
- After reaching the destination node return the distance traveled.
- If the destination node cant be reached then return -1
Below is the implementation of the above approach:
C++
// C++ code for the above approach #include <bits/stdc++.h> using namespace std; class Node { public : int dist, i, j, val; // Constructor Node( int x, int y, int d, int v) { i = x; j = y; dist = d; val = v; } }; // Function to find the length of the // shortest path with neighbor nodes // value not exceeding K int shortestPathLessThanK(vector<vector< int > > mat, int K, int src[], int dest[]) { // Initialize a queue queue<Node*> q; // Add the source node // into the queue Node* Nw = new Node(src[0], src[1], 0, mat[src[0]][src[1]]); q.push(Nw); // Initialize rows and cols int N = mat.size(), M = mat[0].size(); // Initialize a boolean matrix // to keep track of visited cells bool visited[N][M]; for ( int i = 0; i < N; i++) { for ( int j = 0; j < M; j++) { visited[i][j] = false ; } } // Initialize the directions int dir[4][2] = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } }; // Apply BFS while (!q.empty()) { Node* curr = q.front(); q.pop(); // If cell is already visited if (visited[curr->i][curr->j]) continue ; // Mark current node as visited visited[curr->i][curr->j] = true ; // Return the answer after // reaching the destination node if (curr->i == dest[0] && curr->j == dest[1]) return curr->dist; // Explore neighbors for ( int i = 0; i < 4; i++) { int x = dir[i][0] + curr->i, y = dir[i][1] + curr->j; // If out of bounds or already visited // or difference in neighbor nodes // values is greater than K if (x < 0 || y < 0 || x == N || y == M || visited[x][y] || abs (curr->val - mat[x][y]) > K) continue ; // Add current cell into the queue Node* n = new Node(x, y, curr->dist + 1, mat[x][y]); q.push(n); } } // No path exists return -1 return -1; } // Driver function int main() { // Initialize the matrix vector<vector< int > > mat = { { -1, 0, 4, 3 }, { 6, 5, 7, 8 }, { 2, 1, 2, 0 } }; int K = 4; // Source node int src[] = { 0, 0 }; // Destination node int dest[] = { 2, 3 }; // Call the function // and print the answer cout << (shortestPathLessThanK(mat, K, src, dest)); } // This code is contributed by Potta Lokesh |
Java
// Java implementation for the above approach import java.io.*; import java.util.*; import java.lang.Math; class GFG { static class Node { int dist, i, j, val; // Constructor public Node( int i, int j, int dist, int val) { this .i = i; this .j = j; this .dist = dist; this .val = val; } } // Function to find the length of the // shortest path with neighbor nodes // value not exceeding K public static int shortestPathLessThanK( int [][] mat, int K, int [] src, int [] dest) { // Initialize a queue Queue<Node> q = new LinkedList<>(); // Add the source node // into the queue q.add( new Node(src[ 0 ], src[ 1 ], 0 , mat[src[ 0 ]][src[ 1 ]])); // Initialize rows and cols int N = mat.length, M = mat[ 0 ].length; // Initialize a boolean matrix // to keep track of visited cells boolean [][] visited = new boolean [N][M]; // Initialize the directions int [][] dir = { { - 1 , 0 }, { 1 , 0 }, { 0 , 1 }, { 0 , - 1 } }; // Apply BFS while (!q.isEmpty()) { Node curr = q.poll(); // If cell is already visited if (visited[curr.i][curr.j]) continue ; // Mark current node as visited visited[curr.i][curr.j] = true ; // Return the answer after // reaching the destination node if (curr.i == dest[ 0 ] && curr.j == dest[ 1 ]) return curr.dist; // Explore neighbors for ( int i = 0 ; i < 4 ; i++) { int x = dir[i][ 0 ] + curr.i, y = dir[i][ 1 ] + curr.j; // If out of bounds or already visited // or difference in neighbor nodes // values is greater than K if (x < 0 || y < 0 || x == N || y == M || visited[x][y] || Math.abs(curr.val - mat[x][y]) > K) continue ; // Add current cell into the queue q.add( new Node(x, y, curr.dist + 1 , mat[x][y])); } } // No path exists return -1 return - 1 ; } // Driver code public static void main(String[] args) { // Initialize the matrix int [][] mat = { { - 1 , 0 , 4 , 3 }, { 6 , 5 , 7 , 8 }, { 2 , 1 , 2 , 0 } }; int K = 4 ; // Source node int [] src = { 0 , 0 }; // Destination node int [] dest = { 2 , 3 }; // Call the function // and print the answer System.out.println( shortestPathLessThanK(mat, K, src, dest)); } } |
C#
// C# implementation for the above approach using System; using System.Collections.Generic; public class GFG { class Node { public int dist, i, j, val; // Constructor public Node( int i, int j, int dist, int val) { this .i = i; this .j = j; this .dist = dist; this .val = val; } } // Function to find the length of the // shortest path with neighbor nodes // value not exceeding K public static int shortestPathLessThanK( int [,] mat, int K, int [] src, int [] dest) { // Initialize a queue Queue<Node> q = new Queue<Node>(); // Add the source node // into the queue q.Enqueue( new Node(src[0], src[1], 0, mat[src[0],src[1]])); // Initialize rows and cols int N = mat.GetLength(0), M = mat.GetLength(1); // Initialize a bool matrix // to keep track of visited cells bool [,] visited = new bool [N,M]; // Initialize the directions int [,] dir = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } }; // Apply BFS while (q.Count!=0) { Node curr = q.Peek(); q.Dequeue(); // If cell is already visited if (visited[curr.i,curr.j]) continue ; // Mark current node as visited visited[curr.i,curr.j] = true ; // Return the answer after // reaching the destination node if (curr.i == dest[0] && curr.j == dest[1]) return curr.dist; // Explore neighbors for ( int i = 0; i < 4; i++) { int x = dir[i,0] + curr.i, y = dir[i,1] + curr.j; // If out of bounds or already visited // or difference in neighbor nodes // values is greater than K if (x < 0 || y < 0 || x == N || y == M || visited[x,y] || Math.Abs(curr.val - mat[x,y]) > K) continue ; // Add current cell into the queue q.Enqueue( new Node(x, y, curr.dist + 1, mat[x,y])); } } // No path exists return -1 return -1; } // Driver code public static void Main(String[] args) { // Initialize the matrix int [,] mat = { { -1, 0, 4, 3 }, { 6, 5, 7, 8 }, { 2, 1, 2, 0 } }; int K = 4; // Source node int [] src = { 0, 0 }; // Destination node int [] dest = { 2, 3 }; // Call the function // and print the answer Console.WriteLine( shortestPathLessThanK(mat, K, src, dest)); } } // This code is contributed by shikhasingrajput |
Javascript
<script> // Javascript code for the above approach class Node { // Constructor constructor(x, y, d, v) { this .i = x; this .j = y; this .dist = d; this .val = v; } }; // Function to find the length of the // shortest path with neighbor nodes // value not exceeding K function shortestPathLessThanK(mat, K, src, dest) { // Initialize a queue let q = []; // Add the source node // into the queue let Nw = new Node(src[0], src[1], 0, mat[src[0]][src[1]]); q.unshift(Nw); // Initialize rows and cols let N = mat.length, M = mat[0].length; // Initialize a boolean matrix // to keep track of visited cells let visited = new Array(N).fill(0).map(() => new Array(M).fill(0)); for (let i = 0; i < N; i++) { for (let j = 0; j < M; j++) { visited[i][j] = false ; } } // Initialize the directions let dir = [[-1, 0], [1, 0], [0, 1], [0, -1]]; // Apply BFS while (q.length) { let curr = q[q.length - 1]; q.pop(); // If cell is already visited if (visited[curr.i][curr.j]) continue ; // Mark current node as visited visited[curr.i][curr.j] = true ; // Return the answer after // reaching the destination node if (curr.i == dest[0] && curr.j == dest[1]) return curr.dist; // Explore neighbors for (let i = 0; i < 4; i++) { let x = dir[i][0] + curr.i, y = dir[i][1] + curr.j; // If out of bounds or already visited // or difference in neighbor nodes // values is greater than K if (x < 0 || y < 0 || x == N || y == M || visited[x][y] || Math.abs(curr.val - mat[x][y]) > K) continue ; // Add current cell into the queue let n = new Node(x, y, curr.dist + 1, mat[x][y]); q.unshift(n); } } // No path exists return -1 return -1; } // Driver function // Initialize the matrix let mat = [[-1, 0, 4, 3], [6, 5, 7, 8], [2, 1, 2, 0]]; let K = 4; // Source node let src = [0, 0]; // Destination node let dest = [2, 3]; // Call the function // and print the answer document.write(shortestPathLessThanK(mat, K, src, dest)); // This code is contributed by gfgking. </script> |
Python3
# Python code for the above approach import queue class Node: def __init__( self , i, j, dist, val): self .i = i self .j = j self .dist = dist self .val = val # Function to find the length of the # shortest path with neighbor nodes # value not exceeding K def shortest_path_less_than_k(mat, K, src, dest): # Initialize a Queue q = queue.Queue() # Add the source Node # into the queue q.put(Node(src[ 0 ], src[ 1 ], 0 , mat[src[ 0 ]][src[ 1 ]])) # Initialize rows and columns N = len (mat) M = len (mat[ 0 ]) # Initialize a boolean matrix # to keep track of visited cells visited = [[ False for j in range (M)] for i in range (N)] dir = [[ - 1 , 0 ], [ 1 , 0 ], [ 0 , 1 ], [ 0 , - 1 ]] while not q.empty(): curr = q.get() # if already visited skip the rest if visited[curr.i][curr.j]: continue # marking it as visited visited[curr.i][curr.j] = True # Return the answer after reaching dest node if curr.i = = dest[ 0 ] and curr.j = = dest[ 1 ]: return curr.dist for i in range ( 4 ): x = dir [i][ 0 ] + curr.i y = dir [i][ 1 ] + curr.j # If out of bounds or already visited # or difference in neighbor nodes values is greater than K if x < 0 or y < 0 or x = = N or y = = M or visited[x][y] or abs (curr.val - mat[x][y]) > K: continue # add current cell into the queue q.put(Node(x, y, curr.dist + 1 , mat[x][y])) return - 1 mat = [[ - 1 , 0 , 4 , 3 ], [ 6 , 5 , 7 , 8 ], [ 2 , 1 , 2 , 0 ]] k = 4 src = [ 0 , 0 ] dest = [ 2 , 3 ] print (shortest_path_less_than_k(mat, k, src, dest)) |
7
Time Complexity: O(N * M)
Auxiliary Space: O(N * M)
Another approach for above problem :
- Initialize a distance matrix to store the shortest distance from the source cell to each cell.
- Mark the source cell as visited and initialize its distance to 0.
- Initialize a priority queue to store the cells to be processed, and add the source cell to the priority queue.
- While the priority queue is not empty, pop the cell with the minimum distance from the priority queue.
- If the popped cell is the destination cell, return its distance.
- Explore the neighbors of the popped cell. If the difference between the neighbor node value and the current node value is less than or equal to K, calculate the distance to the neighbor cell and update the distance if it is shorter than the previously calculated distance. Add the neighbor cell to the priority queue.
- If the destination cell is not reachable from the source cell, return -1.
Python3
import heapq def shortest_path_less_than_k(mat, K, src, dest): # Initialize rows and columns N = len (mat) M = len (mat[ 0 ]) # Initialize a distance matrix to store the shortest distance from src to each cell dist = [[ float ( 'inf' ) for j in range (M)] for i in range (N)] # Mark the source cell as visited and initialize its distance to 0 dist[src[ 0 ]][src[ 1 ]] = 0 # Initialize a priority queue to store the cells to be processed pq = [] # Add the source cell to the priority queue heapq.heappush(pq, ( 0 , src[ 0 ], src[ 1 ], mat[src[ 0 ]][src[ 1 ]])) dir = [[ - 1 , 0 ], [ 1 , 0 ], [ 0 , 1 ], [ 0 , - 1 ]] while pq: # Pop the cell with the minimum distance from the priority queue curr_dist, curr_i, curr_j, curr_val = heapq.heappop(pq) # If the popped cell is the destination cell, return its distance if curr_i = = dest[ 0 ] and curr_j = = dest[ 1 ]: return curr_dist # Explore the neighbors of the popped cell for d in dir : i, j = curr_i + d[ 0 ], curr_j + d[ 1 ] if i < 0 or i > = N or j < 0 or j > = M: continue neighbor_val = mat[i][j] # If the difference between the neighbor node value and the current node value is less than or equal to K if abs (neighbor_val - curr_val) < = K: # Calculate the distance to the neighbor cell neighbor_dist = curr_dist + 1 # Update the distance if it is shorter than the previously calculated distance if neighbor_dist < dist[i][j]: dist[i][j] = neighbor_dist # Add the neighbor cell to the priority queue heapq.heappush(pq, (neighbor_dist, i, j, neighbor_val)) # If the destination cell is not reachable from the source cell, return -1 return - 1 # code mat = [[ - 1 , 0 , 4 , 3 ], [ 6 , 5 , 7 , 8 ], [ 2 , 1 , 2 , 0 ]] k = 4 src = [ 0 , 0 ] dest = [ 2 , 3 ] print (shortest_path_less_than_k(mat, k, src, dest)) |
7
Time Complexity: O(NM log(NM))
Auxiliary Space: O(NM)
Please Login to comment...