Open In App

Minimum number of given operations required to make two strings equal

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:

  1. If _ is at position i then _ can be swapped with a character at position i+1 or i-1.
  2. 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.
  3. 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:
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:

Below is the implementation of the above approach: 




// 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 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 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 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




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

Article Tags :