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));
}
} |
Output
2