Given an N * M matrix mat[][] consisting of lower case characters, the task is to find the minimum cost to reach from the cell mat[0][0] to the cell mat[N-1][M-1]. If you are at a cell mat[i][j], you can jump to the cells mat[i+1][j], mat[i][j+1], mat[i-1][j], mat[i][j-1] (without going out of bounds) with a cost of 1. Additionally, you can jump to any cell mat[m][n] such that mat[n][m] = mat[i][j] with a cost of 0.
Examples:
Input: mat[][] = {“abc”, “efg”, “hij”}
Output: 4
One of the shortest path will be:
{0, 0} -> {0, 1} -> {0, 2} -> {1, 2} -> {2, 2}
All the edges have a weight of 1, thus the answer is 4.
Input: mat[][] = {“abc”, “efg”, “hbj”}
Output: 2
{0, 0} -> {0, 1} -> {2, 1} -> {2, 2}
1 + 0 + 1 = 2
Naive approach: One approach for solving this problem will be 0-1 BFS. Visualise the setup as a graph with N * M nodes. All the nodes will be connected to adjacent nodes with an edge of weight 1 and the nodes with the same characters with an edge with weight 0. Now, BFS can be used to find the shortest path from the cell mat[0][0] to the cell mat[N-1][M-1]. The time complexity of this will be O((N * M)2) because the number of edges will be of the order O((N * M)2).
Efficient approach: For each character X, find all the characters it is adjacent to. Now, create a graph with a number of nodes as the number of distinct characters in the string each representing a character.
Each node X will have an edge of weight 1 with all the nodes representing the characters adjacent to the character X in the real graph. Then a BFS can be run from the node representing mat[0][0] to the node representing mat[N-1][M-1] in this new graph. The time complexity of this approach will be O(N * M) for pre-processing the graph and the time complexity for running the BFS can be considered constant.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; const int MAX = 26; // Function to return // the value (x - 97) int f( int x) { return x - 'a' ; } // Function to return the minimum cost int findMinCost(vector<string> arr) { int n = arr.size(); int m = arr[0].size(); // Graph vector<vector< int > > gr(MAX); // Adjacency matrix bool edge[MAX][MAX]; // Initialising the adjacency matrix for ( int k = 0; k < MAX; k++) for ( int l = 0; l < MAX; l++) edge[k][l] = 0; // Creating the adjacency matrix for ( int i = 0; i < n; i++) for ( int j = 0; j < m; j++) { if (i + 1 < n and !edge[f(arr[i][j])][f(arr[i + 1][j])]) { gr[f(arr[i][j])].push_back(f(arr[i + 1][j])); edge[f(arr[i][j])][f(arr[i + 1][j])] = 1; } if (j - 1 >= 0 and !edge[f(arr[i][j])][f(arr[i][j - 1])]) { gr[f(arr[i][j])].push_back(f(arr[i][j - 1])); edge[f(arr[i][j])][f(arr[i][j - 1])] = 1; } if (j + 1 < m and !edge[f(arr[i][j])][f(arr[i][j + 1])]) { gr[f(arr[i][j])].push_back(f(arr[i][j + 1])); edge[f(arr[i][j])][f(arr[i][j + 1])] = 1; } if (i - 1 >= 0 and !edge[f(arr[i][j])][f(arr[i - 1][j])]) { gr[f(arr[i][j])].push_back(f(arr[i - 1][j])); edge[f(arr[i][j])][f(arr[i - 1][j])] = 1; } } // Queue to perform BFS queue< int > q; q.push(arr[0][0] - 'a' ); // Visited array bool v[MAX] = { 0 }; // To store the depth of BFS int d = 0; // BFS while (q.size()) { // Number of elements in // the current level int cnt = q.size(); // Inner loop while (cnt--) { // Current element int curr = q.front(); // Popping queue q.pop(); // If the current node has // already been visited if (v[curr]) continue ; v[curr] = 1; // Checking if the current // node is the required node if (curr == arr[n - 1][m - 1] - 'a' ) return d; // Iterating through the current node for ( auto it : gr[curr]) q.push(it); } // Updating the depth d++; } return -1; } // Driver code int main() { vector<string> arr = { "abc" , "def" , "gbi" }; cout << findMinCost(arr); return 0; } |
Java
// Java implementation of the approach import java.util.*; class GFG { static int MAX = 26 ; // Function to return // the value (x - 97) static int f( int x) { return x - 'a' ; } // Function to return the minimum cost static int findMinCost(String[] arr) { int n = arr.length; int m = arr[ 0 ].length(); // Graph Vector<Integer>[] gr = new Vector[MAX]; for ( int i = 0 ; i < MAX; i++) gr[i] = new Vector<Integer>(); // Adjacency matrix boolean [][] edge = new boolean [MAX][MAX]; // Initialising the adjacency matrix for ( int k = 0 ; k < MAX; k++) for ( int l = 0 ; l < MAX; l++) edge[k][l] = false ; // Creating the adjacency matrix for ( int i = 0 ; i < n; i++) for ( int j = 0 ; j < m; j++) { if (i + 1 < n && !edge[f(arr[i].charAt(j))][f(arr[i + 1 ].charAt(j))]) { gr[f(arr[i].charAt(j))].add(f(arr[i + 1 ].charAt(j))); edge[f(arr[i].charAt(j))][f(arr[i + 1 ].charAt(j))] = true ; } if (j - 1 >= 0 && !edge[f(arr[i].charAt(j))][f(arr[i].charAt(j - 1 ))]) { gr[f(arr[i].charAt(j))].add(f(arr[i].charAt(j - 1 ))); edge[f(arr[i].charAt(j))][f(arr[i].charAt(j - 1 ))] = true ; } if (j + 1 < m && !edge[f(arr[i].charAt(j))][f(arr[i].charAt(j + 1 ))]) { gr[f(arr[i].charAt(j))].add(f(arr[i].charAt(j + 1 ))); edge[f(arr[i].charAt(j))][f(arr[i].charAt(j + 1 ))] = true ; } if (i - 1 >= 0 && !edge[f(arr[i].charAt(j))][f(arr[i - 1 ].charAt(j))]) { gr[f(arr[i].charAt(j))].add(f(arr[i - 1 ].charAt(j))); edge[f(arr[i].charAt(j))][f(arr[i - 1 ].charAt(j))] = true ; } } // Queue to perform BFS Queue<Integer> q = new LinkedList<Integer>(); q.add(arr[ 0 ].charAt( 0 ) - 'a' ); // Visited array boolean [] v = new boolean [MAX]; // To store the depth of BFS int d = 0 ; // BFS while (q.size() > 0 ) { // Number of elements in // the current level int cnt = q.size(); // Inner loop while (cnt-- > 0 ) { // Current element int curr = q.peek(); // Popping queue q.remove(); // If the current node has // already been visited if (v[curr]) continue ; v[curr] = true ; // Checking if the current // node is the required node if (curr == arr[n - 1 ].charAt(m - 1 ) - 'a' ) return d; // Iterating through the current node for (Integer it : gr[curr]) q.add(it); } // Updating the depth d++; } return - 1 ; } // Driver code public static void main(String[] args) { String[] arr = { "abc" , "def" , "gbi" }; System.out.print(findMinCost(arr)); } } // This code is contributed by 29AjayKumar |
Python3
# Python3 implementation of the approach MAX = 26 # Function to return # the value (x - 97) def f(x): return ord (x) - ord ( 'a' ) # Function to return the minimum cost def findMinCost( arr): global MAX n = len (arr) m = len (arr[ 0 ]) # Graph gr = [] for x in range ( MAX ): gr.append([]) # Adjacency matrix edge = [] # Initialising the adjacency matrix for k in range ( MAX ): edge.append([]) for l in range ( MAX ): edge[k].append( 0 ) # Creating the adjacency matrix for i in range (n): for j in range (m): if (i + 1 < n and edge[f(arr[i][j])][f(arr[i + 1 ][j])] = = 0 ): gr[f(arr[i][j])].append(f(arr[i + 1 ][j])) edge[f(arr[i][j])][f(arr[i + 1 ][j])] = 1 if (j - 1 > = 0 and edge[f(arr[i][j])][f(arr[i][j - 1 ])] = = 0 ): gr[f(arr[i][j])].append(f(arr[i][j - 1 ])) edge[f(arr[i][j])][f(arr[i][j - 1 ])] = 1 if (j + 1 < m and edge[f(arr[i][j])][f(arr[i][j + 1 ])] = = 0 ): gr[f(arr[i][j])].append(f(arr[i][j + 1 ])) edge[f(arr[i][j])][f(arr[i][j + 1 ])] = 1 if (i - 1 > = 0 and edge[f(arr[i][j])][f(arr[i - 1 ][j])] = = 0 ): gr[f(arr[i][j])].append(f(arr[i - 1 ][j])) edge[f(arr[i][j])][f(arr[i - 1 ][j])] = 1 # Queue to perform BFS q = [] q.append( ord (arr[ 0 ][ 0 ]) - ord ( 'a' )) # Visited array v = [] for i in range ( MAX ): v.append( 0 ) # To store the depth of BFS d = 0 # BFS while ( len (q) > 0 ): # Number of elements in # the current level cnt = len (q) # Inner loop while (cnt > 0 ): cnt = cnt - 1 # Current element curr = q[ 0 ] # Popping queue q.pop( 0 ) # If the current node has # already been visited if (v[curr] ! = 0 ): continue v[curr] = 1 # Checking if the current # node is the required node if (curr = = ( ord (arr[n - 1 ][m - 1 ]) - ord ( 'a' ))): return d # Iterating through the current node for it in gr[curr]: q.append(it) # Updating the depth d = d + 1 return - 1 # Driver code arr = [ "abc" , "def" , "gbi" ] print ( findMinCost(arr)) # This code is contributed by Arnab Kundu |
C#
// C# implementation of the approach using System; using System.Collections.Generic; class GFG { static int MAX = 26; // Function to return // the value (x - 97) static int f( int x) { return x - 'a' ; } // Function to return the minimum cost static int findMinCost(String[] arr) { int n = arr.Length; int m = arr[0].Length; // Graph List< int >[] gr = new List< int >[MAX]; for ( int i = 0; i < MAX; i++) gr[i] = new List< int >(); // Adjacency matrix bool [,] edge = new bool [MAX, MAX]; // Initialising the adjacency matrix for ( int k = 0; k < MAX; k++) for ( int l = 0; l < MAX; l++) edge[k,l] = false ; // Creating the adjacency matrix for ( int i = 0; i < n; i++) for ( int j = 0; j < m; j++) { if (i + 1 < n && !edge[f(arr[i][j]),f(arr[i + 1][j])]) { gr[f(arr[i][j])].Add(f(arr[i + 1][j])); edge[f(arr[i][j]), f(arr[i + 1][j])] = true ; } if (j - 1 >= 0 && !edge[f(arr[i][j]),f(arr[i][j - 1])]) { gr[f(arr[i][j])].Add(f(arr[i][j - 1])); edge[f(arr[i][j]), f(arr[i][j - 1])] = true ; } if (j + 1 < m && !edge[f(arr[i][j]),f(arr[i][j + 1])]) { gr[f(arr[i][j])].Add(f(arr[i][j + 1])); edge[f(arr[i][j]), f(arr[i][j + 1])] = true ; } if (i - 1 >= 0 && !edge[f(arr[i][j]),f(arr[i - 1][j])]) { gr[f(arr[i][j])].Add(f(arr[i - 1][j])); edge[f(arr[i][j]), f(arr[i - 1][j])] = true ; } } // Queue to perform BFS Queue< int > q = new Queue< int >(); q.Enqueue(arr[0][0] - 'a' ); // Visited array bool [] v = new bool [MAX]; // To store the depth of BFS int d = 0; // BFS while (q.Count > 0) { // Number of elements in // the current level int cnt = q.Count; // Inner loop while (cnt-- > 0) { // Current element int curr = q.Peek(); // Popping queue q.Dequeue(); // If the current node has // already been visited if (v[curr]) continue ; v[curr] = true ; // Checking if the current // node is the required node if (curr == arr[n - 1][m - 1] - 'a' ) return d; // Iterating through the current node foreach ( int it in gr[curr]) q.Enqueue(it); } // Updating the depth d++; } return -1; } // Driver code public static void Main(String[] args) { String[] arr = { "abc" , "def" , "gbi" }; Console.Write(findMinCost(arr)); } } // This code is contributed by 29AjayKumar |
Javascript
// Javascript implementation of the approach const MAX = 26; // Function to return the value (x - 97) function f(x) { return x.charCodeAt(0) - 'a' .charCodeAt(0); } // Function to return the minimum cost function findMinCost(arr) { let n = arr.length; let m = arr[0].length; // Graph let gr = []; for (let x = 0; x < MAX; x++) { gr.push([]); } // Adjacency matrix let edge = []; // Initializing the adjacency matrix for (let k = 0; k < MAX; k++) { edge.push([]); for (let l = 0; l < MAX; l++) { edge[k].push(0); } } // Creating the adjacency matrix for (let i = 0; i < n; i++) { for (let j = 0; j < m; j++) { if (i + 1 < n && edge[f(arr[i][j])][f(arr[i + 1][j])] === 0) { gr[f(arr[i][j])].push(f(arr[i + 1][j])); edge[f(arr[i][j])][f(arr[i + 1][j])] = 1; } if (j - 1 >= 0 && edge[f(arr[i][j])][f(arr[i][j - 1])] === 0) { gr[f(arr[i][j])].push(f(arr[i][j - 1])); edge[f(arr[i][j])][f(arr[i][j - 1])] = 1; } if (j + 1 < m && edge[f(arr[i][j])][f(arr[i][j + 1])] === 0) { gr[f(arr[i][j])].push(f(arr[i][j + 1])); edge[f(arr[i][j])][f(arr[i][j + 1])] = 1; } if (i - 1 >= 0 && edge[f(arr[i][j])][f(arr[i - 1][j])] === 0) { gr[f(arr[i][j])].push(f(arr[i - 1][j])); edge[f(arr[i][j])][f(arr[i - 1][j])] = 1; } } } // Queue to perform BFS let q = []; q.push(arr[0][0].charCodeAt(0) - 'a' .charCodeAt(0)); // Visited array let v = []; for (let i = 0; i < MAX; i++) { v.push(0); } // To store the depth of BFS let d = 0; // BFS while (q.length > 0) { // Number of elements in the current level let cnt = q.length; // Inner loop while (cnt > 0) { cnt--; // Current element let curr = q[0]; // Popping queue q.shift(); // If the current node has already been visited if (v[curr] !== 0) continue ; v[curr] = 1; // Checking if the current node is the required node if (curr === (arr[n - 1][m - 1].charCodeAt(0) - 'a' .charCodeAt(0))) return d; // Iterating through the current node for (let it of gr[curr]) { q.push(it); } } // Updating the depth d++; } return -1; }; // Driver code let arr = [ 'abc' , 'def' , 'gbi' ]; console.log(findMinCost(arr)); |
2
Time Complexity: O(N * M).
Auxiliary Space: O(N * M).
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!