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 Bint 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 codeint main(){ string A = "aba_a"; string B = "_baaa"; cout << minOperations(A, B); return 0;} |
Java
// Java implementation of the above approachimport 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 approachfrom collections import deque# Function to return the minimum number of# operations to convert string A to Bdef 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 Codeif __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 Bfunction 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 Codelet 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!

… [Trackback]
[…] Read More to that Topic: geeksforgeeks.org/minimum-number-of-given-operations-required-to-make-two-strings-equal/ […]
… [Trackback]
[…] There you can find 88266 additional Information to that Topic: geeksforgeeks.org/minimum-number-of-given-operations-required-to-make-two-strings-equal/ […]