Monday, November 18, 2024
Google search engine
HomeData Modelling & AIRearrange characters in a String such that no two adjacent characters are...

Rearrange characters in a String such that no two adjacent characters are same

Given a string with lowercase repeated characters, the task is to rearrange characters in a string so that no two adjacent characters are the same. If it is not possible to do so, then print “Not possible”.

Examples: 

Input: aaabc 
Output: abaca 

Input: aaabb
Output: ababa 

Input: aa 
Output: Not Possible

Input: aaaabc 
Output: Not Possible

Asked In: Amazon Interview  

Recommended Practice

To solve the problem using this approach follow the below idea:

The idea is to put the highest frequency character first (a greedy approach). Use a priority queue (Or Binary Max Heap) and put all characters and ordered by their frequencies (highest frequency character at root). One by one take the highest frequency character from the heap and add it to result. After adding it, just decrease the frequency of the character and then temporarily move this character out of priority queue so that it is not picked again next time.

Follow the given steps to solve the problem:

  • Build a Priority_queue or max_heap, pq that stores characters with their frequencies. 
    • Priority_queue or max_heap is built on the basis of the frequency of character. 
  • Create a temporary Key that will be used as the previously visited element (the previous element in the resultant string. Initialize it { char = ‘#’ , freq = ‘-1’ } 
  • While pq is not empty. 
    • Pop an element and add it to the result. 
    • Decrease the frequency of the popped element by ‘1’ 
    • Push the previous element back into the priority_queue if its frequency is greater than zero. 
    • Make the current element as the previous element for the next iteration. 
  • If the length of the resultant string and the original string is not equal, then print “not possible”, else print the resultant string.

Below is the implementation of the above approach:

C++




// C++ program to rearrange characters in a string
// so that no two adjacent characters are same.
 
#include <bits/stdc++.h>
using namespace std;
 
const int MAX_CHAR = 26;
 
struct Key {
 
    int freq; // store frequency of character
    char ch;
 
    // Function for priority_queue to store Key
    // according to freq
    bool operator<(const Key& k) const
    {
        return freq < k.freq;
    }
};
 
// Function to rearrange character of a string
// so that no char repeat twice
void rearrangeString(string str)
{
    int N = str.length();
 
    // Store frequencies of all characters in string
    int count[MAX_CHAR] = { 0 };
    for (int i = 0; i < N; i++)
        count[str[i] - 'a']++;
 
    // Insert all characters with their frequencies
    // into a priority_queue
    priority_queue<Key> pq;
    for (char c = 'a'; c <= 'z'; c++) {
        int val = c - 'a';
        if (count[val]) {
            pq.push(Key{ count[val], c });
        }
    }
 
    // 'str' that will store resultant value
    str = "";
 
    // work as the previous visited element
    // initial previous element be. ( '#' and
    // it's frequency '-1' )
    Key prev{ -1, '#' };
 
    // traverse queue
    while (!pq.empty()) {
        // pop top element from queue and add it
        // to string.
        Key k = pq.top();
        pq.pop();
        str = str + k.ch;
 
        // IF frequency of previous character is less
        // than zero that means it is useless, we
        // need not to push it
        if (prev.freq > 0)
            pq.push(prev);
 
        // Make current character as the previous 'char'
        // decrease frequency by 'one'
        (k.freq)--;
        prev = k;
    }
 
    // If length of the resultant string and original
    // string is not same then string is not valid
    if (N != str.length())
        cout << " Not possible " << endl;
 
    else // valid string
        cout << str << endl;
}
 
// Driver's code
int main()
{
    string str = "bbbaa";
 
    // Function call
    rearrangeString(str);
    return 0;
}


Java




// Java program to rearrange characters in a string
// so that no two adjacent characters are same.
 
import java.io.*;
import java.util.*;
 
class KeyComparator implements Comparator<Key> {
 
    // Overriding compare()method of Comparator
    public int compare(Key k1, Key k2)
    {
        if (k1.freq < k2.freq)
            return 1;
        else if (k1.freq > k2.freq)
            return -1;
        return 0;
    }
}
 
class Key {
 
    int freq; // store frequency of character
    char ch;
    Key(int val, char c)
    {
        freq = val;
        ch = c;
    }
}
 
class GFG {
    static int MAX_CHAR = 26;
 
    // Function to rearrange character of a string
    // so that no char repeat twice
    static void rearrangeString(String str)
    {
        int n = str.length();
 
        // Store frequencies of all characters in string
        int[] count = new int[MAX_CHAR];
 
        for (int i = 0; i < n; i++)
            count[str.charAt(i) - 'a']++;
 
        // Insert all characters with their
        // frequencies into a priority_queue
        PriorityQueue<Key> pq
            = new PriorityQueue<>(new KeyComparator());
        for (char c = 'a'; c <= 'z'; c++) {
            int val = c - 'a';
            if (count[val] > 0)
                pq.add(new Key(count[val], c));
        }
 
        // 'str' that will store resultant value
        str = "";
 
        // work as the previous visited element
        // initial previous element be. ( '#' and
        // it's frequency '-1' )
        Key prev = new Key(-1, '#');
 
        // traverse queue
        while (pq.size() != 0) {
 
            // pop top element from queue and
            // add it to string.
            Key k = pq.peek();
            pq.poll();
            str = str + k.ch;
 
            // If frequency of previous character
            // is less than zero that means it is
            // useless, we need not to push it
            if (prev.freq > 0)
                pq.add(prev);
 
            // make current character as the previous
            // 'char' decrease frequency by 'one'
            (k.freq)--;
            prev = k;
        }
 
        // If length of the resultant string
        // and original string is not same then
        // string is not valid
        if (n != str.length())
            System.out.println(" Not possible ");
        else
            System.out.println(str);
    }
 
    // Driver's code
    public static void main(String args[])
    {
        String str = "bbbaa";
 
        // Function call
        rearrangeString(str);
    }
}
 
// This code is contributed by rachana soma


Python3




# Python program to rearrange characters in a string
# so that no two adjacent characters are same.
 
from heapq import heappush, heappop
from collections import Counter
 
# A key class for readability
 
 
class Key:
    def __init__(self, character: str, freq: int) -> None:
        self.character = character
        self.freq = freq
 
    def __lt__(self, other: "Key") -> bool:
        return self.freq > other.freq
 
 
# Function to rearrange character of a string
# so that no char repeat twice
def rearrangeString(str: str):
    n = len(str)
    # Creating a frequency hashmap
    count = dict()
    for i in str:
        count[ord(i)] = count.get(ord(i), 0) + 1
 
    pq = []
    for c in range(97, 123):
        if count.get(c, 0):
            heappush(pq, Key(chr(c), count))
 
    # null character for default previous checking
    prev = Key('#', -1)
    str = ""
 
    while pq:
        key = heappop(pq)
        str += key.character
 
        # Since one character is already added
        key.freq -= 1
 
        # We avoid inserting if the frequency drops to 0
        if prev.freq > 0:
            heappush(pq, prev)
 
        prev = key
 
    if len(str) != n:
        print("Not possible")
    else:
        print(str)
 
 
# Driver's Code
if __name__ == "__main__":
    string = "bbbaa"
 
    # Function call
    rearrangeString(string)
 
    # This code is contributed by kraanzu.


C#




// C# code
using System;
 
public class GFG
{
 
  // Maximum number of characters
  const int MAX_CHAR = 26;
 
  // Structure to store character and its
  // frequency in the string
  public struct Key
  {
    public int freq;
    public char ch;
 
    // Function to compare two Key values
    public int CompareTo(Key other)
    {
      return freq - other.freq;
    }
  };
 
  // Function to rearrange character of a string
  // so that no char repeat twice
  public static void rearrangeString(String str)
  {
    int N = str.Length;
 
    // Store frequencies of all characters in string
    int[] count = new int[MAX_CHAR];
    for (int i = 0; i < N; i++)
      count[str[i] - 'a']++;
 
    // Insert all characters with their frequencies
    // into a priority_queue
    PriorityQueue<Key> pq = new PriorityQueue<Key>();
    for (int c = 'a'; c <= 'z'; c++)
    {
      int val = c - 'a';
      if (count[val] > 0)
        pq.Enqueue(new Key(count[val], (char)c));
    }
 
    // 'str' that will store resultant value
    str = "";
 
    // work as the previous visited element
    // initial previous element be. ( '#' and
    // it's frequency '-1' )
    Key prev = new Key(-1, '#');
 
    // traverse queue
    while (pq.Count != 0)
    {
      // pop top element from queue and add it
      // to string.
      Key k = pq.Dequeue();
      str += k.ch;
 
      // IF frequency of previous character is less
      // than zero that means it is useless, we
      // need not to push it
      if (prev.freq > 0)
        pq.Enqueue(prev);
 
      // Make current character as the previous 'char'
      // decrease frequency by 'one'
      (k.freq)--;
      prev = k;
    }
 
    // If length of the resultant string and original
    // string is not same then string is not valid
    if (N != str.Length)
      Console.WriteLine(" Not possible ");
 
    else // valid string
      Console.WriteLine(str);
  }
 
  // Driver's code
  public static void Main()
  {
    String str = "bbbaa";
 
    // Function call
    rearrangeString(str);
  }
}
 
// This code is contributed by ishankhandelwals.


Javascript




// JS code
const MAX_CHAR = 26;
 
const rearrangeString = (str) => {
  let N = str.length;
 
  // Store frequencies of all characters in string
  let count = Array(MAX_CHAR).fill(0);
  for (let i = 0; i < N; i++) {
    count[str.charCodeAt(i) - 'a'.charCodeAt(0)]++;
  }
 
  // Insert all characters with their frequencies
  // into a priority_queue
  let pq = [];
  for (let c = 'a'; c <= 'z'; c++) {
    let val = c.charCodeAt(0) - 'a'.charCodeAt(0);
    if (count[val]) {
      pq.push({ freq: count[val], ch: c });
    }
  }
 
  // 'str' that will store resultant value
  str = "";
 
  // work as the previous visited element
  // initial previous element be. ( '#' and
  // it's frequency '-1' )
  let prev = { freq: -1, ch: '#' };
 
  // traverse queue
  while (pq.length > 0) {
    // pop top element from queue and add it
    // to string.
    let k = pq.shift();
    str = str + k.ch;
 
    // IF frequency of previous character is less
    // than zero that means it is useless, we
    // need not to push it
    if (prev.freq > 0) pq.push(prev);
 
    // Make current character as the previous 'char'
    // decrease frequency by 'one'
    k.freq--;
    prev = k;
  }
 
  // If length of the resultant string and original
  // string is not same then string is not valid
  if (N != str.length) {
    console.log(" Not possible ");
  } else // valid string
    console.log(str);
  }
};
 
// This code is contributed by ishankhandelwals.


Output

babab

Time complexity : O(N log(N))
Auxiliary Space: O(N), Extra space is used to store the resultant string

Rearrange characters in a String such that no two adjacent characters are same using Frequency:

To solve the problem using this approach follow the below idea:

Fill all the even positions of the result string first, with the highest frequency character. If there are still some even positions remaining, fill them first. Once even positions are done, then fill the odd positions. This way, it can be ensured that no two adjacent characters are the same. 

Follow the given steps to solve the problem:

  • Calculate the frequencies of every character in the input string
  • If a character with a maximum frequency has a frequency greater than (n + 1) / 2, then return an empty string, as it is not possible to construct a string
  • Now fill the even index positions with the maximum frequency character, if some even positions are remaining then first fill them with remaining characters
  • Then fill odd index positions with the remaining characters
  • Return the constructed string

Below is the implementation of the above approach:

C




// C code for the above approach
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
char getMaxCountChar(int count[])
{
    int max = 0;
    char ch;
    for (int i = 0; i < 26; i++) {
        if (count[i] > max) {
            max = count[i];
            ch = 'a' + i;
        }
    }
 
    return ch;
}
 
char* rearrangeString(char S[])
{
    int N = strlen(S);
    if (N == 0)
        return "";
 
    int count[26] = { 0 };
    for (int i = 0; i < N; i++)
        count[S[i] - 'a']++;
 
    char ch_max = getMaxCountChar(count);
    int maxCount = count[ch_max - 'a'];
 
    char* res = malloc(N * sizeof(int));
    int ind = 0;
 
    // check if the result is possible or not
    if (maxCount > (N + 1) / 2)
        return res;
 
    // filling the most frequently occurring char in the
    // even indices
    while (maxCount) {
        res[ind] = ch_max;
        ind = ind + 2;
        maxCount--;
    }
 
    count[ch_max - 'a'] = 0;
 
    // Now filling the other Chars, first
    // filling the even positions and then
    // the odd positions
    for (int i = 0; i < 26; i++) {
 
        while (count[i] > 0) {
 
            ind = (ind >= N) ? 1 : ind;
            res[ind] = 'a' + i;
            ind += 2;
            count[i]--;
        }
    }
 
    return res;
}
 
// Driver's code
int main()
{
    char str[] = { "bbbaa" };
 
    // Function call
    char* res = rearrangeString(str);
    if (res == "")
        printf("Not possible \n");
    else
        printf("%s \n", res);
 
    return 0;
}


C++14




// C++ code for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
char getMaxCountChar(vector<int>& count)
{
    int max = 0;
    char ch;
    for (int i = 0; i < 26; i++) {
        if (count[i] > max) {
            max = count[i];
            ch = 'a' + i;
        }
    }
 
    return ch;
}
 
string rearrangeString(string S)
{
    int N = S.size();
    if (N == 0)
        return "";
 
    vector<int> count(26, 0);
    for (auto& ch : S)
        count[ch - 'a']++;
 
    char ch_max = getMaxCountChar(count);
    int maxCount = count[ch_max - 'a'];
 
    // check if the result is possible or not
    if (maxCount > (n + 1) / 2)
        return "";
 
    string res(n, ' ');
    int ind = 0;
 
    // filling the most frequently occurring char in the
    // even indices
    while (maxCount) {
        res[ind] = ch_max;
        ind = ind + 2;
        maxCount--;
    }
 
    count[ch_max - 'a'] = 0;
 
    // now filling the other Chars, first
    // filling the even positions and then
    // the odd positions
    for (int i = 0; i < 26; i++) {
 
        while (count[i] > 0) {
 
            ind = (ind >= n) ? 1 : ind;
            res[ind] = 'a' + i;
            ind += 2;
            count[i]--;
        }
    }
 
    return res;
}
 
// Driver's code
int main()
{
    string str = "bbbaa";
 
    // Function call
    string res = rearrangeString(str);
    if (res == "")
        cout << "Not possible" << endl;
    else
        cout << res << endl;
 
    return 0;
}


Java




// Java code for the above approach
 
import java.io.*;
 
class GFG {
    static char getMaxCountChar(int[] count)
    {
        int max = 0;
        char ch = 0;
        for (int i = 0; i < 26; i++) {
            if (count[i] > max) {
                max = count[i];
                ch = (char)((int)'a' + i);
            }
        }
        return ch;
    }
 
    static String rearrangeString(String S)
    {
 
        int N = S.length();
        if (N == 0)
            return "";
 
        int[] count = new int[26];
        for (int i = 0; i < 26; i++) {
            count[i] = 0;
        }
        for (char ch : S.toCharArray()) {
            count[(int)ch - (int)'a']++;
        }
 
        char ch_max = getMaxCountChar(count);
        int maxCount = count[(int)ch_max - (int)'a'];
 
        // check if the result is possible or not
        if (maxCount > (N + 1) / 2)
            return "";
 
        String res = "";
        for (int i = 0; i < N; i++) {
            res += ' ';
        }
 
        int ind = 0;
        // filling the most frequently occurring char in the
        // even indices
        while (maxCount > 0) {
            res = res.substring(0, ind) + ch_max
                  + res.substring(ind + 1);
            ind = ind + 2;
            maxCount--;
        }
        count[(int)ch_max - (int)'a'] = 0;
 
        // now filling the other Chars, first filling the
        // even positions and then the odd positions
        for (int i = 0; i < 26; i++) {
            while (count[i] > 0) {
                ind = (ind >= N) ? 1 : ind;
                res = res.substring(0, ind)
                      + (char)((int)'a' + i)
                      + res.substring(ind + 1);
                ind += 2;
                count[i]--;
            }
        }
        return res;
    }
 
    // Driver's Code
    public static void main(String args[])
    {
        String str = "bbbaa";
 
        // Function call
        String res = rearrangeString(str);
        if (res == "")
            System.out.println("Not possible");
        else
            System.out.println(res);
    }
}
 
// This code is contributed by shinjanpatra


Python3




# Python program for rearranging characters in a string such
# that no two adjacent are same
 
# Function to find the char with maximum frequency in the given
# string
 
 
def getMaxCountChar(count):
    maxCount = 0
    for i in range(26):
        if count[i] > maxCount:
            maxCount = count[i]
            maxChar = chr(i + ord('a'))
 
    return maxCount, maxChar
 
# Main function for rearranging the characters
 
 
def rearrangeString(S):
    N = len(S)
 
    # if length of string is None return False
    if not N:
        return False
 
    # create a hashmap for the alphabets
    count = [0] * 26
    for char in S:
        count[ord(char) - ord('a')] += 1
 
    maxCount, maxChar = getMaxCountChar(count)
 
    # if the char with maximum frequency is more than the half of the
    # total length of the string than return False
    if maxCount > (N + 1) // 2:
        return False
 
    # create a list for storing the result
    res = [None] * N
 
    ind = 0
 
    # place all occurrences of the char with maximum frequency in
    # even positions
    while maxCount:
        res[ind] = maxChar
        ind += 2
        maxCount -= 1
 
    # replace the count of the char with maximum frequency to zero
    # as all the maxChar are already placed in the result
    count[ord(maxChar) - ord('a')] = 0
 
    # place all other char in the result starting from remaining even
    # positions and then place in the odd positions
    for i in range(26):
        while count[i] > 0:
            if ind >= N:
                ind = 1
            res[ind] = chr(i + ord('a'))
            ind += 2
            count[i] -= 1
 
    # convert the result list to string and return
    return ''.join(res)
 
 
# Driver Code
if __name__ == '__main__':
    str = 'bbbaa'
 
    # Function call
    res = rearrangeString(str)
    if res:
        print(res)
    else:
        print('Not possible')
 
# This code is contributed by Manish Thapa


C#




// C# code
using System;
   
public class GFG
{
   
    // Maximum number of characters
    const int MAX_CHAR = 26;
   
    // Structure to store character and its
    // frequency in the string
    public struct Key
    {
        public int freq;
        public char ch;
   
        // Function to compare two Key values
        public int CompareTo(Key other)
        {
            return freq - other.freq;
        }
    };
   
    // Function to rearrange character of a string
    // so that no char repeat twice
    public static void rearrangeString(String str)
    {
        int N = str.Length;
   
        // Store frequencies of all characters in string
        int[] count = new int[MAX_CHAR];
        for (int i = 0; i < N; i++)
            count[str[i] - 'a']++;
   
        // Insert all characters with their frequencies
        // into a priority_queue
        PriorityQueue<Key> pq = new PriorityQueue<Key>();
        for (int c = 'a'; c <= 'z'; c++)
        {
            int val = c - 'a';
            if (count[val] > 0)
                pq.Enqueue(new Key(count[val], (char)c));
        }
   
        // 'str' that will store resultant value
        str = "";
   
        // work as the previous visited element
        // initial previous element be. ( '#' and
        // it's frequency '-1' )
        Key prev = new Key(-1, '#');
   
        // traverse queue
        while (pq.Count != 0)
        {
            // pop top element from queue and add it
            // to string.
            Key k = pq.Dequeue();
            str += k.ch;
   
            // IF frequency of previous character is less
            // than zero that means it is useless, we
            // need not to push it
            if (prev.freq > 0)
                pq.Enqueue(prev);
   
            // Make current character as the previous 'char'
            // decrease frequency by 'one'
            (k.freq)--;
            prev = k;
        }
   
        // If length of the resultant string and original
        // string is not same then string is not valid
        if (N != str.Length)
            Console.WriteLine(" Not possible ");
   
        else // valid string
            Console.WriteLine(str);
    }
   
    // Driver's code
    public static void Main()
    {
        String str = "bbbaa";
   
        // Function call
        rearrangeString(str);
    }
}


Javascript




// JavaScript program for rearranging characters in a string such
// that no two adjacent are same
 
// Function to find the char with maximum frequency in the given
// string
function getMaxCountChar(count){
let maxCount = 0
let maxChar
for(let i = 0; i < 26; i++){
    if(count[i] > maxCount){
        maxCount = count[i]
        maxChar = String.fromCharCode(i + ('a').charCodeAt(0))
  }
}
 
return [maxCount, maxChar]
}
 
// Main function for rearranging the characters
function rearrangeString(S){
let n = S.length
 
// if length of string is None return false
if(!n)
    return false
     
// create a hashmap for the alphabets
let count = new Array(26).fill(0)
for(let char of S)
    count[char.charCodeAt(0) - ('a').charCodeAt(0)] += 1
 
let [maxCount, maxChar] = getMaxCountChar(count)
 
// if the char with maximum frequency is more than the half of the
// total length of the string than return false
if(maxCount > Math.floor((n + 1) / 2))
    return false
 
// create a list for storing the result
let res = new Array(n)
 
let ind = 0
 
// place all occurrences of the char with maximum frequency in
// even positions
while(maxCount){
    res[ind] = maxChar
    ind += 2
    maxCount -= 1
}
     
// replace the count of the char with maximum frequency to zero
// as all the maxChar are already placed in the result
count[maxChar.charCodeAt(0) - 'a'.charCodeAt(0)] = 0
 
// place all other char in the result starting from remaining even
// positions and then place in the odd positions
for(let i = 0; i < 26; i++)
{
    while(count[i] > 0)
    {
        if(ind >= n)
            ind = 1
        res[ind] = String.fromCharCode(i + ('a').charCodeAt(0))
        ind += 2
        count[i] -= 1
  }
}
 
// convert the result list to string and return
return res.join('')
}
 
// Driver Code
let str = 'bbbaa'
let res = rearrangeString(str)
if(res)
  document.write(res)
else
  document.write('Not valid string')
 
// This code is contributed by shinjanpatra


Output

babab 

Time complexity: O(N)
Auxiliary Space: O(N+26), as there are 26 lowercase english characters

This article is contributed by Nishant Singh . If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments