Open In App

Rearrange a string so that all same characters become d distance away

Last Updated : 23 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s and a positive integer d, rearrange the characters of the string so that any two identical characters are at least d positions apart. If no such arrangement is possible, print "Cannot be rearranged".

Examples:

Input: s="abb", d = 2
Output: "bab"
Explanation: The character 'a' and 'b' need to be rearranged such that 'b' appears at least 2 positions away from the other 'b'. One valid solution is "bab", where the two 'b's are at positions 2 and 3, satisfying the distance requirement.

Input: s="aacbbc", d = 3
Output: "abcabc"
Explanation: The characters are rearranged so that each pair of identical characters ('a', 'b', 'c') are placed at least 3 positions apart. One valid solution is "abcabc".

Input: s="geeksforgeeks", d = 3
Output: "egkegkesfesor"
Explanation: The characters are rearranged such that identical characters are at least 3 positions apart. One valid solution is "egkegkesfesor".

Input: s="aaa", d = 2
Output: "Cannot be rearranged"
Explanation: It's impossible to rearrange the characters of the string such that 'a' appears more than once and still respects the required distance of 2.

[Naive Approach] Checking all permutations - O(n! * n^2) time and O(n) space

The idea is to generate all permutations of the string and checks each one to see if identical characters are at least d positions apart. It guarantees finding a solution if it exists but is inefficient due to the factorial growth of permutations (n!).

C++
#include <bits/stdc++.h>
using namespace std;

// Function to check if all identical characters are at least d positions apart
bool valid(const string &s, int d) {
    for (int i = 0; i < s.length(); i++) {
        for (int j = i + 1; j < s.length(); j++) {
            // Check if characters are the same and too close to each other
            if (s[i] == s[j] && abs(i - j) < d) {
                return false;
            }
        }
    }
    return true;
}

bool rearrange(string s, int d) {
    // Sort the string to start with the lexicographically smallest permutation
    sort(s.begin(), s.end());

    // Try all permutations of the string
    do {
        // For each permutation, check if it satisfies the condition
        if (valid(s, d)) {
            // If valid, print the arrangement and return true
            cout << s << endl;
            return true;
        }
    } while (next_permutation(s.begin(), s.end())); // Generate next permutation

    // If no valid arrangement is found, print a message and return false
    cout << "Cannot be rearranged" << endl;
    return false;
}

int main() {
    string s="aabbcc";
    int d=3;

    rearrange(s, d);

    return 0;
}
Java
import java.util.*;

public class GfG{
    // Function to check if all identical characters are at least d positions apart
    static boolean valid(String s, int d) {
        for (int i = 0; i < s.length(); i++) {
            for (int j = i + 1; j < s.length(); j++) {
                // Check if characters are the same and too close to each other
                if (s.charAt(i) == s.charAt(j) && Math.abs(i - j) < d) {
                    return false;
                }
            }
        }
        return true;
    }

    static boolean rearrange(String s, int d) {
        // Convert string to character array and sort
        char[] arr = s.toCharArray();
        Arrays.sort(arr);
        s = new String(arr);

        // Try all permutations of the string
        do {
            // For each permutation, check if it satisfies the condition
            if (valid(s, d)) {
                // If valid, print the arrangement and return true
                System.out.println(s);
                return true;
            }
        } while ((s = nextPermutation(s)) != null);

        // If no valid arrangement is found, print a message and return false
        System.out.println("Cannot be rearranged");
        return false;
    }

    static String nextPermutation(String s) {
        char[] arr = s.toCharArray();
        int i = arr.length - 1;
        while (i > 0 && arr[i - 1] >= arr[i]) i--;
        if (i <= 0) return null;
        int j = arr.length - 1;
        while (arr[j] <= arr[i - 1]) j--;
        char temp = arr[i - 1];
        arr[i - 1] = arr[j];
        arr[j] = temp;
        j = arr.length - 1;
        while (i < j) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
        return new String(arr);
    }

    public static void main(String[] args) {
        String s = "aabbcc";
        int d = 3;
        rearrange(s, d);
    }
}
Python
# Function to check if all identical characters are at least d positions apart
def valid(s, d):
    for i in range(len(s)):
        for j in range(i + 1, len(s)):
            # Check if characters are the same and too close to each other
            if s[i] == s[j] and abs(i - j) < d:
                return False
    return True

from itertools import permutations

def rearrange(s, d):
    # Sort the string to start with the lexicographically smallest permutation
    s = ''.join(sorted(s))

    # Try all permutations of the string
    for perm in permutations(s):
        # For each permutation, check if it satisfies the condition
        if valid(perm, d):
            # If valid, print the arrangement and return true
            print(''.join(perm))
            return True

    # If no valid arrangement is found, print a message and return false
    print("Cannot be rearranged")
    return False

s = "aabbcc"
d = 3
rearrange(s, d)
C#
using System;
using System.Linq;

class Program {
    // Function to check if all identical characters are at least d positions apart
    static bool Valid(string s, int d) {
        for (int i = 0; i < s.Length; i++) {
            for (int j = i + 1; j < s.Length; j++) {
                // Check if characters are the same and too close to each other
                if (s[i] == s[j] && Math.Abs(i - j) < d) {
                    return false;
                }
            }
        }
        return true;
    }

    static bool Rearrange(string s, int d) {
        // Sort the string to start with the lexicographically smallest permutation
        char[] arr = s.ToCharArray();
        Array.Sort(arr);
        s = new string(arr);

        // Try all permutations of the string
        do {
            // For each permutation, check if it satisfies the condition
            if (Valid(s, d)) {
                // If valid, print the arrangement and return true
                Console.WriteLine(s);
                return true;
            }
        } while ((s = NextPermutation(s)) != null);

        // If no valid arrangement is found, print a message and return false
        Console.WriteLine("Cannot be rearranged");
        return false;
    }

    static string NextPermutation(string s) {
        char[] arr = s.ToCharArray();
        int i = arr.Length - 1;
        while (i > 0 && arr[i - 1] >= arr[i]) i--;
        if (i <= 0) return null;
        int j = arr.Length - 1;
        while (arr[j] <= arr[i - 1]) j--;
        char temp = arr[i - 1];
        arr[i - 1] = arr[j];
        arr[j] = temp;
        j = arr.Length - 1;
        while (i < j) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
        return new string(arr);
    }

    static void Main() {
        string s = "aabbcc";
        int d = 3;
        Rearrange(s, d);
    }
}
JavaScript
// Function to check if all identical characters are at least d positions apart
function valid(s, d) {
    for (let i = 0; i < s.length; i++) {
        for (let j = i + 1; j < s.length; j++) {
            // Check if characters are the same and too close to each other
            if (s[i] === s[j] && Math.abs(i - j) < d) {
                return false;
            }
        }
    }
    return true;
}

function rearrange(s, d) {
    // Sort the string to start with the lexicographically smallest permutation
    s = s.split('').sort().join('');

    let found = false; // Flag to track if a valid arrangement is found

    // Try all permutations of the string
    const permute = (str, l, r) => {
        if (l === r) {
            // For each permutation, check if it satisfies the condition
            if (valid(str, d)) {
                // If valid, print the arrangement and return true
                console.log(str);
                found = true;
                return true;
            }
        } else {
            for (let i = l; i <= r; i++) {
                str = swap(str, l, i);
                if (permute(str, l + 1, r)) return true;
                str = swap(str, l, i); // backtrack
            }
        }
        return false;
    };

    const swap = (s, i, j) => {
        const charArray = s.split('');
        [charArray[i], charArray[j]] = [charArray[j], charArray[i]];
        return charArray.join('');
    };

    // Start permuting
    permute(s, 0, s.length - 1);

    // If no valid arrangement found, print the failure message
    if (!found) {
        console.log("Cannot be rearranged");
    }
}

const s = "aabbcc";
const d = 3;
rearrange(s, d);

Output
abcabc

Time Complexity: O(n! * n2), n! for generating all permutations
Auxiliary space : O(n)

[Expected Approach] Using Max Heap - O(n + m * log m) time and O(n) space

The idea is to use a greedy algorithm to place the most frequent characters first, ensuring identical characters are at least d positions apart. A max heap selects the frequent characters, and the string is filled by placing characters at intervals of d, maintaining the required distance. At any point, if we are not able to place, we return. At the end, if we are able to place all, we return the result string.

C++
#include <bits/stdc++.h>
using namespace std;

void rearrange(string s, int d) {
    int n = s.size();
    
    // Frequency map for characters
    unordered_map<char, int> freq;

    // Calculate frequencies of each character
    for (int i = 0; i < n; i++) {
        freq[s[i]]++;
        s[i]='\0';
    }

    // Create a max heap
    priority_queue<pair<int, char>,vector<pair<int,char>>,greater<pair<int,char>>> pq;
    
    // Insert frequencies and characters into a max-heap
    for (auto& entry : freq) {
        pq.push({entry.second, entry.first});
    }

    // Rearrange characters in the string
    while (!pq.empty()) {
        char ch = pq.top().second;
        int f = pq.top().first;
        pq.pop();

        // Find positions in the string and assign characters
        int pos = 0;
        while(s[pos]!='\0')
        {
            pos++;    
        }
        
        while (f--) {
            
            // If position exceeds the size of 
            // the string, cannot rearrange
            if (pos >= n) {
                cout << "Cannot be rearranged";
                return;
            }
            s[pos] = ch;
            pos += d;
        }
    }

    cout << s;
}

int main() {
    string s = "aabbcc"; 
    rearrange(s, 3);

    return 0;
}
Java
import java.util.*;

public class Rearrange {
    public static void rearrange(String s, int d) {
        int n = s.length();

        // Frequency map for characters
        Map<Character, Integer> freq = new HashMap<>();
        for (char ch : s.toCharArray()) {
            freq.put(ch, freq.getOrDefault(ch, 0) + 1);
        }

        // Max heap (sorting by frequency in descending order)
        PriorityQueue<Map.Entry<Character, Integer>> pq = 
            new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());

        pq.addAll(freq.entrySet());

        // Result array
        char[] result = new char[n];
        Arrays.fill(result, '\u0000');

        // Queue to store delayed elements
        Queue<Map.Entry<Character, Integer>> waitQueue = new LinkedList<>();

        int index = 0;

        while (!pq.isEmpty()) {
            Map.Entry<Character, Integer> current = pq.poll();
            char ch = current.getKey();
            int count = current.getValue();

            for (int i = 0; i < count; i++) {
                // Find the next available position
                while (index < n && result[index] != '\u0000') {
                    index++;
                }

                if (index >= n) {
                    System.out.println("Cannot be rearranged");
                    return;
                }

                result[index] = ch;
                index += d;  // Place next occurrence `d` positions apart

                // If index exceeds n, reset it to the
                // first available position
                if (index >= n) {
                    index = 0;
                    while (index < n && result[index] != '\u0000') {
                        index++;
                    }
                }
            }

            if (count > 1) {
                waitQueue.add(new AbstractMap.SimpleEntry<>(ch, count - 1));
            }

            // After `d` iterations, reinsert from the waitQueue
            if (waitQueue.size() >= d) {
                pq.offer(waitQueue.poll());
            }
        }

        System.out.println(new String(result));
    }

    public static void main(String[] args) {
        String s = "aabbcc";
        rearrange(s, 3);
    }
}
Python
import heapq

def rearrange(s, d):
    n = len(s)
    
    # Frequency map for characters
    freq = {}

    # Calculate frequencies of each character
    for char in s:
        freq[char] = freq.get(char, 0) + 1

    # Create a max heap (negative count for max heap behavior)
    pq = [(-count, char) for char, count in freq.items()]
    heapq.heapify(pq)

    # Result array initialized with empty spaces
    result = [''] * n
    
    # List to store waiting characters
    wait_queue = []
    
    while pq:
        count, ch = heapq.heappop(pq)
        count = -count  # Convert back to positive
        
        # Find the first available position
        pos = 0
        while pos < n and result[pos] != '':
            pos += 1

        for _ in range(count):
            if pos >= n:
                print("Cannot be rearranged")
                return
            
            result[pos] = ch
            pos += d
        
        # After using this character, add to wait_queue
        if count > 1:
            wait_queue.append((count - 1, ch))
        
        # If we have processed `d` elements, we can 
        # push back waiting elements
        if len(wait_queue) >= d:
            heapq.heappush(pq, (-wait_queue[0][0], wait_queue[0][1]))
            wait_queue.pop(0)

    print("".join(result))

# Example usage
s = "aabbcc"
rearrange(s, 3)
C#
using System;
using System.Linq;
using System.Collections.Generic;

class GFG
{
	static void rearrange(char[] str, int d)
	{
		// Length of the string
		int n = str.Length;
	
		// A structure to store a character and its frequency
		Dictionary<char, int> m = new Dictionary<char, int> ();
	
		// Traverse the input string and store frequencies of
		// all characters.
		for (int i = 0; i < n; i++) {
			if (!m.ContainsKey(str[i]))
				m[str[i]] = 0;
			m[str[i]]++;
			str[i] = '\0';
		}
	
		// max-heap
		List<Tuple<char, int>> pq = new List<Tuple<char, int>>();
		foreach (var entry in m)
		{
			pq.Add(Tuple.Create(entry.Key, entry.Value));
		}
		pq = pq.OrderBy(a => a.Item2).ThenBy(a => a.Item1).ToList();
		
		// Now one by one extract all distinct characters from
		// heap and put them back in str[] with the d
		// distance constraint
		while (pq.Count > 0) {
			char x = pq[0].Item1;
			
			// Find the first available position in str[]
			int p = 0;
			while (str[p] != '\0')
				p++;
			
			// Fill x at p, p+d, p+2d, .. p+(frequency-1)d
			for (int k = 0; k < pq[0].Item2; k++) {
			
				// If the index goes beyond size, then string
				// cannot be rearranged.
				if (p + d * k >= n) {
					Console.WriteLine ("Cannot be rearranged");
					return;
				}
				str[p + d * k] = x;
			}
			pq.RemoveAt(0);
		}
	}

	public static void Main(string[] args)
	{
		char[] str = "aabbcc".ToCharArray();

		rearrange(str, 3);
		Console.WriteLine(new string(str));
	}
}
JavaScript
// Function to rearrange characters in a string
function rearrange(s, d) {
    let n = s.length;
    
    // Frequency map for characters
    let freq = {};

    // Calculate frequencies of each character
    for (let char of s) {
        freq[char] = (freq[char] || 0) + 1;
    }

    // Create a max heap
    let pq = [];
    
    // Insert frequencies and characters into a max-heap
    for (let char in freq) {
        pq.push([-freq[char], char]);
    }
    pq.sort();

    // Rearrange characters in the string
    let result = new Array(n).fill('');
    
    while (pq.length > 0) {
        let [count, ch] = pq.shift();
        count = -count;

        // Find positions in the string and assign characters
        let pos = 0;
        while (pos < n && result[pos] !== '') {
            pos++;
        }
        
        for (let i = 0; i < count; i++) {
            
            // If position exceeds the size of the 
            // string, cannot rearrange
            if (pos >= n) {
                console.log('Cannot be rearranged');
                return;
            }
            result[pos] = ch;
            pos += d;
        }
    }

    console.log(result.join(''));
}

// Example usage
let s = 'aabbcc';
rearrange(s, 3);

Output
abcabc

Time Complexity: (n + m * log m), m is maximum number of distinct character in string
Auxiliary space : O(n)


Article Tags :

Similar Reads