Minimum swaps to group similar characters side by side?

Given a string, find minimum no of swaps(not necessarily adjacent) to convert it into a string which have similar characters side by side.

Examples:

Input : abcb
Output : 1
Explanation : swap (c, b) to form abbc or acbb. Number of swap operations for this is 1;



Input : abbaacb
0123456
Output : 2
Explanation : Swap 0th index with 6th index and then swap 5th index with 6th index.

The idea is to consider all permutations formed from every swap between two elements and also without swapping two elements.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

#include <bits/stdc++.h>
using namespace std;
  
// checks whether a string has similar characters side by side
bool sameCharAdj(string str)
{
    int n = str.length(), i;
    set<char> st;
    st.insert(str[0]);
    for (i = 1; i < n; i++) {
  
        // If similar chars side by side, continue
        if (str[i] == str[i - 1])
            continue;
         
        // If we have found a char equal to current
        // char and does not exist side to it, 
        // return false
        if (st.find(str[i]) != st.end())
            return false;
  
        st.insert(str[i]);
    }
    return true;
}
  
// counts min swap operations to convert a string 
// that has similar characters side by side
int minSwaps(string str, int l, int r, int cnt, int minm)
{
   // Base case 
   if (l == r) {
        if (sameCharAdj(str))
            return cnt;
        else
            return INT_MAX;
    }
     
    for (int i = l + 1; i <= r; i++) {
        swap(str[i], str[l]);
        cnt++;
  
        // considering swapping of i and l chars 
        int x = minSwaps(str, l + 1, r, cnt, minm); 
  
        // Backtrack
        swap(str[i], str[l]);
        cnt--;
  
        // not considering swapping of i and l chars
        int y = minSwaps(str, l + 1, r, cnt, minm);
  
        // taking min of above two 
        minm = min(minm, min(x, y)); 
    }
  
    return minm;
}
  
// Driver code
int main()
{
    string str = "abbaacb";
    int n = str.length(), cnt = 0, minm = INT_MAX;
    cout << minSwaps(str, 0, n - 1, cnt, minm) << endl;
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

import java.util.*;
  
class GFG {
  
// checks whether a String has similar characters side by side
    static boolean sameJavaharAdj(char str[]) {
        int n = str.length, i;
        TreeSet<Character> st = new TreeSet<>();
        st.add(str[0]);
        for (i = 1; i < n; i++) {
  
            // If similar chars side by side, continue
            if (str[i] == str[i - 1]) {
                continue;
            }
  
            // If we have found a char equal to current
            // char and does not exist side to it, 
            // return false
            if (st.contains(str[i]) & (str[i] != st.last())) {
                return false;
            }
            st.add(str[i]);
        }
        return true;
    }
  
// counts min swap operations to convert a String 
// that has similar characters side by side
    static int minSwaps(char str[], int l, int r, int cnt, int minm) {
        // Base case 
        if (l == r) {
            if (sameJavaharAdj(str)) {
                return cnt;
            } else {
                return Integer.MAX_VALUE;
            }
        }
  
        for (int i = l + 1; i <= r; i++) {
            swap(str, i, l);
            cnt++;
  
            // considering swapping of i and l chars 
            int x = minSwaps(str, l + 1, r, cnt, minm);
  
            // Backtrack
            swap(str, i, l);
            cnt--;
  
            // not considering swapping of i and l chars
            int y = minSwaps(str, l + 1, r, cnt, minm);
  
            // taking Math.min of above two 
            minm = Math.min(minm, Math.min(x, y));
        }
  
        return minm;
    }
  
    static void swap(char[] arr, int i, int j) {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
// Driver code
  
    public static void main(String[] args) {
        String str = "abbaacb";
        int n = str.length(), cnt = 0, minm = Integer.MAX_VALUE;
        System.out.print(minSwaps(str.toCharArray(), 0, n - 1, cnt, minm));;
    }
}
// This code is contributed Rajput-Ji

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach
from sys import maxsize
  
# checks whether a string has 
# similar characters side by side
def sameCharAdj(string):
    n = len(string)
    st = set()
    st.add(string[0])
  
    for i in range(1, n):
  
        # If similar chars side by side, continue
        if string[i] == string[i - 1]:
            continue
  
        # If we have found a char equal to current
        # char and does not exist side to it,
        # return false
        if string[i] in st:
            return False
  
        st.add(string[i])
    return True
  
# counts min swap operations to convert a string
# that has similar characters side by side
def minSwaps(string, l, r, cnt, minm):
  
    # Base case
    if l == r:
        if sameCharAdj(string):
            return cnt
        else:
            return maxsize
  
    for i in range(l + 1, r + 1, 1):
        string[i], string[l] = string[l], string[i]
        cnt += 1
  
        # considering swapping of i and l chars
        x = minSwaps(string, l + 1, r, cnt, minm)
  
        # Backtrack
        string[i], string[l] = string[l], string[i]
        cnt -= 1
  
        # not considering swapping of i and l chars
        y = minSwaps(string, l + 1, r, cnt, minm)
  
        # taking min of above two
        minm = min(minm, min(x, y))
  
    return minm
  
# Driver Code
if __name__ == "__main__":
    string = "abbaacb"
    string = list(string)
  
    n = len(string)
    cnt = 0
    minm = maxsize
    print(minSwaps(string, 0, n - 1, cnt, minm))
  
# This code is contributed by
# sanjeev2552

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

using System;
using System.Collections.Generic;
  
class GFG 
{
  
    // checks whether a String has similar 
    // characters side by side
    static bool sameJavaharAdj(char []str)
    {
        int n = str.Length, i;
        HashSet<char> st = new HashSet<char>();
        st.Add(str[0]);
        for (i = 1; i < n; i++) 
        {
  
            // If similar chars side by side, continue
            if (str[i] == str[i - 1]) 
            {
                continue;
            }
  
            // If we have found a char equal to current
            // char and does not exist side to it, 
            // return false
            if (st.Contains(str[i]) & !st.Equals(str[i])) 
            {
                return false;
            }
            st.Add(str[i]);
        }
        return true;
    }
  
    // counts min swap operations to convert a String 
    // that has similar characters side by side
    static int minSwaps(char []str, int l, int r, 
                                int cnt, int minm) 
    {
        // Base case 
        if (l == r) 
        {
            if (sameJavaharAdj(str))
            {
                return cnt;
            
            else
            {
                return int.MaxValue;
            }
        }
  
        for (int i = l + 1; i <= r; i++)
        {
            swap(str, i, l);
            cnt++;
  
            // considering swapping of i and l chars 
            int x = minSwaps(str, l + 1, r, cnt, minm);
  
            // Backtrack
            swap(str, i, l);
            cnt--;
  
            // not considering swapping of i and l chars
            int y = minSwaps(str, l + 1, r, cnt, minm);
  
            // taking Math.min of above two 
            minm = Math.Min(minm, Math.Min(x, y));
        }
  
        return minm;
    }
  
    static void swap(char[] arr, int i, int j) 
    {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
      
    // Driver code
    public static void Main()
    {
        String str = "abbaacb";
        int n = str.Length, cnt = 0, minm = int.MaxValue;
        Console.WriteLine(minSwaps(str.ToCharArray(), 0,
                                    n - 1, cnt, minm));;
    }
}
  
// This code is contributed mits

chevron_right


Output:

2

Time Complexity : The recurrence is T(n) = 2n*T(n-1) + O(n)
So the time complexity is greater than O((2*n)!)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.