Given two strings A and B, both strings contain characters a and b and are of equal lengths. There is one _ (empty space) in both the strings. The task is to convert first string into second string by doing the minimum number of the following operations:
- If _ is at position i then _ can be swapped with a character at position i+1 or i-1.
- If characters at positions i+1 and i+2 are different then _ can be swapped with a character at position i+1 or i+2.
- Similarly, if characters at positions i-1 and i-2 are different then _ can be swapped with a character at position i-1 or i-2.
Examples:
Input: A = “aba_a”, B = “_baaa”
Output: 2
Move 1 : A = “ab_aa” (Swapped A[2] with A[3]) Move 2 : A = “_baaa” (Swapped A[0] with A[2])Input: A = “a_b”, B = “ab_”
Output: 1
Source: Directi Interview Set 7
Approach:
- Apply a simple Breadth First Search over the string and an element of the queue used for BFS will contain the pair str, pos where pos is the position of _ in the string str.
- Also maintain a map vis which will store the string as key and the minimum moves to get to the string as value.
- For every string str from the queue, generate a new string tmp based on the four conditions given and update the vis map as vis[tmp] = vis[str] + 1.
- Repeat the above steps until the queue is empty or the required string is generated i.e. tmp == B
- If the required string is generated then return vis[str] + 1 which is the minimum number of operations required to change A to B.
Below is the implementation of the above approach:
C++
// C++ implementation of the above approach #include <bits/stdc++.h> using namespace std; // Function to return the minimum number of // operations to convert string A to B int minOperations(string s, string f) { // If both the strings are equal then // no operation needs to be performed if (s == f) return 0; unordered_map<string, int > vis; int n; n = s.length(); int pos = 0; for ( int i = 0; i < s.length(); i++) { if (s[i] == '_' ) { // store the position of '_' pos = i; break ; } } // to store the generated string at every // move and the position of '_' within it queue<pair<string, int > > q; q.push({ s, pos }); // vis will store the minimum operations // to reach that particular string vis[s] = 0; while (!q.empty()) { string ss = q.front().first; int pp = q.front().second; // minimum moves to reach the string ss int dist = vis[ss]; q.pop(); // try all 4 possible operations // if '_' can be swapped with // the character on it's left if (pp > 0) { // swap with the left character swap(ss[pp], ss[pp - 1]); // if the string is generated // for the first time if (!vis.count(ss)) { // if generated string is // the required string if (ss == f) { return dist + 1; break ; } // update the distance for the // currently generated string vis[ss] = dist + 1; q.push({ ss, pp - 1 }); } // restore the string before it was // swapped to check other cases swap(ss[pp], ss[pp - 1]); } // swap '_' with the character // on it's right this time if (pp < n - 1) { swap(ss[pp], ss[pp + 1]); if (!vis.count(ss)) { if (ss == f) { return dist + 1; break ; } vis[ss] = dist + 1; q.push({ ss, pp + 1 }); } swap(ss[pp], ss[pp + 1]); } // if '_' can be swapped // with the character 'i+2' if (pp > 1 && ss[pp - 1] != ss[pp - 2]) { swap(ss[pp], ss[pp - 2]); if (!vis.count(ss)) { if (ss == f) { return dist + 1; break ; } vis[ss] = dist + 1; q.push({ ss, pp - 2 }); } swap(ss[pp], ss[pp - 2]); } // if '_' can be swapped // with the character at 'i+2' if (pp < n - 2 && ss[pp + 1] != ss[pp + 2]) { swap(ss[pp], ss[pp + 2]); if (!vis.count(ss)) { if (ss == f) { return dist + 1; break ; } vis[ss] = dist + 1; q.push({ ss, pp + 2 }); } swap(ss[pp], ss[pp + 2]); } } } // Driver code int main() { string A = "aba_a" ; string B = "_baaa" ; cout << minOperations(A, B); return 0; } |
Java
// Java implementation of the above approach import java.util.*; class GFG { // Function to return the minimum number of // operations to convert string A to B static int minOperations(String s, String f) { // If both the strings are equal then // no operation needs to be performed if (s.equals(f)) return 0 ; Map<String, Integer> vis = new HashMap<>(); int n; n = s.length(); int pos = 0 ; for ( int i = 0 ; i < s.length(); i++) { if (s.charAt(i) == '_' ) { // store the position of '_' pos = i; break ; } } // to store the generated string at every // move and the position of '_' within it Queue<Map.Entry<String, Integer>> q = new LinkedList<Map.Entry<String, Integer>>(); q.add( new AbstractMap.SimpleEntry<String, Integer>(s, pos)); // vis will store the minimum operations // to reach that particular string vis.put(s, 0 ); while (!q.isEmpty()) { String ss = q.peek().getKey(); int pp = q.peek().getValue(); // minimum moves to reach the string ss int dist = vis.get(ss); q.remove(); // try all 4 possible operations // if '_' can be swapped with // the character on it's left if (pp > 0 ) { // swap with the left character char [] ch = ss.toCharArray(); char temp = ch[pp]; ch[pp] = ch[pp - 1 ]; ch[pp - 1 ] = temp; ss = String.valueOf(ch); // if the string is generated // for the first time if (!vis.containsKey(ss)) { // if generated string is // the required string if (ss.equals(f)) { return dist + 1 ; } // update the distance for the // currently generated string vis.put(ss, dist + 1 ); q.add( new AbstractMap.SimpleEntry<String, Integer>(ss, pp - 1 )); } // restore the string before it was // swapped to check other cases ch = ss.toCharArray(); temp = ch[pp]; ch[pp] = ch[pp - 1 ]; ch[pp - 1 ] = temp; ss = String.valueOf(ch); } // swap '_' with the character // on it's right this time if (pp < n - 1 ) { char [] ch = ss.toCharArray(); char temp = ch[pp]; ch[pp] = ch[pp + 1 ]; ch[pp + 1 ] = temp; ss = String.valueOf(ch); if (!vis.containsKey(ss)) { if (ss.equals(f)) { return dist + 1 ; } vis.put(ss, dist + 1 ); q.add( new AbstractMap.SimpleEntry<String, Integer>(ss, pp + 1 )); } ch = ss.toCharArray(); temp = ch[pp]; ch[pp] = ch[pp + 1 ]; ch[pp + 1 ] = temp; ss = String.valueOf(ch); } // if '_' can be swapped // with the character 'i+2' if (pp > 1 && ss.charAt(pp - 1 ) != ss.charAt(pp - 2 )) { char [] ch = ss.toCharArray(); char temp = ch[pp]; ch[pp] = ch[pp - 2 ]; ch[pp - 2 ] = temp; ss = String.valueOf(ch); if (!vis.containsKey(ss)) { if (ss.equals(f)) { return dist + 1 ; } vis.put(ss, dist + 1 ); q.add( new AbstractMap.SimpleEntry<String, Integer>(ss, pp - 2 )); } ch = ss.toCharArray(); temp = ch[pp]; ch[pp] = ch[pp - 2 ]; ch[pp - 2 ] = temp; ss = String.valueOf(ch); } // if '_' can be swapped // with the character at 'i+2' if (pp < n - 2 && ss.charAt(pp + 1 ) != ss.charAt(pp + 2 )) { char [] ch = ss.toCharArray(); char temp = ch[pp]; ch[pp] = ch[pp + 2 ]; ch[pp + 2 ] = temp; ss = String.valueOf(ch); if (!vis.containsKey(ss)) { if (ss.equals(f)) { return dist + 1 ; } vis.put(ss, dist + 1 ); q.add( new AbstractMap.SimpleEntry<String, Integer>(ss, pp + 2 )); } ch = ss.toCharArray(); temp = ch[pp]; ch[pp] = ch[pp + 2 ]; ch[pp + 2 ] = temp; ss = String.valueOf(ch); } } return - 1 ; } // Driver code public static void main(String[] args) { String A = "aba_a" ; String B = "_baaa" ; System.out.println(minOperations(A, B)); } } |
Python3
# Python3 implementation of the approach from collections import deque # Function to return the minimum number of # operations to convert string A to B def minOperations(s: str , f: str ) - > int : # If both the strings are equal then # no operation needs to be performed if s = = f: return 0 vis = dict () n = len (s) pos = 0 for i in range (n): if s[i] = = '_' : # store the position of '_' pos = i break # to store the generated string at every # move and the position of '_' within it q = deque() q.append((s, pos)) # vis will store the minimum operations # to reach that particular string vis[s] = 0 while q: ss = q[ 0 ][ 0 ] pp = q[ 0 ][ 1 ] # minimum moves to reach the string ss dist = vis[ss] q.popleft() ss = list (ss) # try all 4 possible operations # if '_' can be swapped with # the character on it's left if pp > 0 : # swap with the left character ss[pp], ss[pp - 1 ] = ss[pp - 1 ], ss[pp] ss = ''.join(ss) # if the string is generated # for the first time if ss not in vis: # if generated string is # the required string if ss = = f: return dist + 1 # update the distance for the # currently generated string vis[ss] = dist + 1 q.append((ss, pp - 1 )) ss = list (ss) # restore the string before it was # swapped to check other cases ss[pp], ss[pp - 1 ] = ss[pp - 1 ], ss[pp] ss = ''.join(ss) # swap '_' with the character # on it's right this time if pp < n - 1 : ss = list (ss) ss[pp], ss[pp + 1 ] = ss[pp + 1 ], ss[pp] ss = ''.join(ss) if ss not in vis: if ss = = f: return dist + 1 vis[ss] = dist + 1 q.append((ss, pp + 1 )) ss = list (ss) ss[pp], ss[pp + 1 ] = ss[pp + 1 ], ss[pp] ss = ''.join(ss) # if '_' can be swapped # with the character 'i+2' if pp > 1 and ss[pp - 1 ] ! = ss[pp - 2 ]: ss = list (ss) ss[pp], ss[pp - 2 ] = ss[pp - 2 ], ss[pp] ss = ''.join(ss) if ss not in vis: if ss = = f: return dist + 1 vis[ss] = dist + 1 q.append((ss, pp - 2 )) ss = list (ss) ss[pp], ss[pp - 2 ] = ss[pp - 2 ], ss[pp] ss = ''.join(ss) # if '_' can be swapped # with the character at 'i+2' if pp < n - 2 and ss[pp + 1 ] ! = ss[pp + 2 ]: ss = list (ss) ss[pp], ss[pp + 2 ] = ss[pp + 2 ], ss[pp] ss = ''.join(ss) if ss not in vis: if ss = = f: return dist + 1 vis[ss] = dist + 1 q.append((ss, pp + 2 )) ss = list (ss) ss[pp], ss[pp + 2 ] = ss[pp + 2 ], ss[pp] ss = ''.join(ss) # Driver Code if __name__ = = "__main__" : A = "aba_a" B = "_baaa" print (minOperations(A, B)) # This code is contributed by # sanjeev2552 |
Javascript
// JavaScript implementation of the approach // Function to return the minimum number of // operations to convert string A to B function minOperations(s, f) { // If both the strings are equal then // no operation needs to be performed if (s === f) { return 0; } let vis = {}; let n = s.length; let pos = 0; for (let i = 0; i < n; i++) { if (s[i] === '_' ) { // store the position of '_' pos = i; break ; } } // to store the generated string at every // move and the position of '_' within it let q = []; q.push([s, pos]); // vis will store the minimum operations // to reach that particular string vis[s] = 0; while (q.length) { let [ss, pp] = q[0]; // minimum moves to reach the string ss let dist = vis[ss]; q.shift(); ss = ss.split( '' ); // try all 4 possible operations // if '_' can be swapped with // the character on it's left if (pp > 0) { // swap with the left character [ss[pp], ss[pp - 1]] = [ss[pp - 1], ss[pp]]; ss = ss.join(' '); // if the string is generated // for the first time if (!(ss in vis)) { // if generated string is // the required string if (ss === f) { return dist + 1; } // update the distance for the // currently generated string vis[ss] = dist + 1; q.push([ss, pp - 1]); } ss = ss.split(' '); // restore the string before it was // swapped to check other cases [ss[pp], ss[pp - 1]] = [ss[pp - 1], ss[pp]]; ss = ss.join(' '); } // swap ' _ ' with the character // on it' s right this time if (pp < n - 1) { ss = ss.split( '' ); [ss[pp], ss[pp + 1]] = [ss[pp + 1], ss[pp]]; ss = ss.join( '' ); if (!(ss in vis)) { if (ss === f) { return dist + 1; } vis[ss] = dist + 1; q.push([ss, pp + 1]); } ss = ss.split( '' ); [ss[pp], ss[pp + 1]] = [ss[pp + 1], ss[pp]]; ss = ss.join( '' ); } // if '_' can be swapped // with the character 'i+2' if (pp > 1 && ss[pp - 1] !== ss[pp - 2]) { ss = ss.split( '' ); [ss[pp], ss[pp - 2]] = [ss[pp - 2], ss[pp]]; ss = ss.join( '' ); if (!(ss in vis)) { if (ss === f) { return dist + 1; } vis[ss] = dist + 1; q.push([ss, pp - 2]); } ss = ss.split( '' ); [ss[pp], ss[pp - 2]] = [ss[pp - 2], ss[pp]]; ss = ss.join( '' ); } // if '_' can be swapped // with the character at 'i+2' if (pp < n - 2 && ss[pp + 1] !== ss[pp + 2]) { ss = ss.split( '' ); [ss[pp], ss[pp + 2]] = [ss[pp + 2], ss[pp]]; ss = ss.join( '' ); if (!(ss in vis)) { if (ss === f) { return dist + 1; } vis[ss] = dist + 1; q.push([ss, pp + 2]); } ss = ss.split( '' ); [ss[pp], ss[pp + 2]] = [ss[pp + 2], ss[pp]]; ss = ss.join( '' ); } } } // Driver Code let A = "aba_a" ; let B = "_baaa" ; console.log(minOperations(A, B)) // This code is contributed by codebraxnzt |
C#
using System; using System.Collections.Generic; class GFG { // Function to return the minimum number of // operations to convert string A to B static int minOperations( string s, string f) { // If both the strings are equal then // no operation needs to be performed if (s == f) return 0; Dictionary< string , int > vis = new Dictionary< string , int >(); int n = s.Length; int pos = 0; for ( int i = 0; i < s.Length; i++) { if (s[i] == '_' ) { // store the position of '_' pos = i; break ; } } // to store the generated string at every // move and the position of '_' within it Queue<Tuple< string , int >> q = new Queue<Tuple< string , int >>(); q.Enqueue( new Tuple< string , int >(s, pos)); // vis will store the minimum operations // to reach that particular string vis[s] = 0; while (q.Count > 0) { string ss = q.Peek().Item1; int pp = q.Peek().Item2; // minimum moves to reach the string ss int dist = vis[ss]; q.Dequeue(); // try all 4 possible operations // if '_' can be swapped with // the character on it's left if (pp > 0) { // swap with the left character char [] arr = ss.ToCharArray(); char temp = arr[pp]; arr[pp] = arr[pp - 1]; arr[pp - 1] = temp; ss = new string (arr); // if the string is generated // for the first time if (!vis.ContainsKey(ss)) { // if generated string is // the required string if (ss == f) return dist + 1; // update the distance for the // currently generated string vis[ss] = dist + 1; q.Enqueue( new Tuple< string , int >(ss, pp - 1)); } // restore the string before it was // swapped to check other cases arr = ss.ToCharArray(); temp = arr[pp]; arr[pp] = arr[pp - 1]; arr[pp - 1] = temp; ss = new string (arr); } // swap '_' with the character // on it's right this time if (pp < n - 1) { char [] arr = ss.ToCharArray(); char temp = arr[pp]; arr[pp] = arr[pp + 1]; arr[pp + 1] = temp; ss = new string (arr); if (!vis.ContainsKey(ss)) { if (ss == f) return dist + 1; vis[ss] = dist + 1; q.Enqueue( new Tuple< string , int >(ss, pp + 1)); } arr = ss.ToCharArray(); temp = arr[pp]; arr[pp] = arr[pp + 1]; arr[pp + 1] = temp; ss = new string (arr); } // if '_' can be swapped // with the character 'i+2' if (pp > 1 && ss[pp - 1] != ss[pp - 2]) { char [] arr = ss.ToCharArray(); char temp = arr[pp]; arr[pp] = arr[pp - 2]; arr[pp - 2] = temp; ss = new string (arr); if (!vis.ContainsKey(ss)) { if (ss == f) { return dist + 1; } vis[ss] = dist + 1; q.Enqueue( new Tuple< string , int >(ss, pp - 2)); } arr = ss.ToCharArray(); temp = arr[pp]; arr[pp] = arr[pp - 2]; arr[pp - 2] = temp; ss = new string (arr); } // if '_' can be swapped // with the character at 'i+2' if (pp < n - 2 && ss[pp + 1] != ss[pp + 2]) { char [] arr = ss.ToCharArray(); char temp = arr[pp]; arr[pp] = arr[pp + 2]; arr[pp + 2] = temp; ss = new string (arr); if (!vis.ContainsKey(ss)) { if (ss == f) { return dist + 1; } vis[ss] = dist + 1; q.Enqueue( new Tuple< string , int >(ss, pp + 2)); } arr = ss.ToCharArray(); temp = arr[pp]; arr[pp] = arr[pp + 2]; arr[pp + 2] = temp; ss = new string (arr); } } return -1; } // Driver code public static void Main() { string A = "aba_a" ; string B = "_baaa" ; Console.Write(minOperations(A, B)); } } |
2
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!