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++ 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 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 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# 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 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).