Rearrange To Make Adjacent Different

Last Updated : 18 Jul, 2026

Given a string s consisting of lowercase English letters, check whether it can be rearranged such that no two adjacent characters are the same.

Examples: 

Input: s = "aaabc"
Output: true
Explanation: "aaabc" can rearranged to "abaca" or "acaba" as no two adjacent characters are same in the output string.

Input: s = "aaabb"
Output: true
Explanation: "aaabb" can rearranged to "ababa" as no two adjacent characters are same in the output string.

Input: s = "aaaabc"
Output: false
Explanation: No combinations possible such that two adjacent characters are different.

Try It Yourself
redirect icon

[Naive Approach] Using Hash Map to Count Frequencies - O(n) Time and O(1) Space

The idea is to count how many times each character appears using a hash map, and look at the highest count among them. A valid rearrangement exists only if this maximum count is at most half the string's length, rounded up (the ceiling of n/2) - any more, and that character alone would need to occupy more than every alternate position, forcing two of its copies to end up next to each other no matter how the string is arranged.

Step by Step Implementation:

  • Count the frequency of every character using a hash map.
  • Find the maximum frequency among all characters.
  • Check if this maximum frequency is at most ⌈n/2⌉ (computed as (n + 1) / 2 using integer division).
  • Return true if the condition holds, false otherwise.
C++
#include <iostream>
#include <string>
using namespace std;

bool canRearrange(string &s) {
    int n = s.size();

    // Voting phase: find a candidate using Boyer-Moore's algorithm
    char candidate = '\0';
    int count = 0;
    for (char ch : s) {
        if (count == 0) {
            candidate = ch;
            count = 1;
        } else if (ch == candidate) {
            count++;
        } else {
            count--;
        }
    }

    // Verification phase: count the candidate's actual occurrences
    count = 0;
    for (char ch : s) {
        if (ch == candidate) {
            count++;
        }
    }

    // Rearrangement is impossible only if some character's frequency
    // exceeds ceil(n / 2)
    return count <= (n + 1) / 2;
}

int main() {
    string s = "aaabc";

    cout << (canRearrange(s) ? "true" : "false") << endl;
    return 0;
}
Java
import java.util.HashMap;

class GFG {
    static boolean canRearrange(String s) {
        int n = s.length();

        // Count the frequency of every character
        HashMap<Character, Integer> freq = new HashMap<>();
        for (char ch : s.toCharArray()) {
            freq.put(ch, freq.getOrDefault(ch, 0) + 1);
        }

        // Find the maximum frequency among all characters
        int maxFreq = 0;
        for (int val : freq.values()) {
            maxFreq = Math.max(maxFreq, val);
        }

        // Rearrangement is possible only if the maximum frequency
        // does not exceed ceil(n / 2)
        return maxFreq <= (n + 1) / 2;
    }

    public static void main(String[] args) {
        String s = "aaabc";

        System.out.println(canRearrange(s));
    }
}
Python
from collections import Counter


def canRearrange(s):
    n = len(s)

    # Count the frequency of every character
    freq = Counter(s)

    # Find the maximum frequency among all characters
    maxFreq = max(freq.values())

    # Rearrangement is possible only if the maximum frequency
    # does not exceed ceil(n / 2)
    return maxFreq <= (n + 1) // 2


s = "aaabc"

print("true" if canRearrange(s) else "false")
C#
using System;
using System.Collections.Generic;
using System.Linq;

class GFG {
    static bool canRearrange(string s) {
        int n = s.Length;

        // Count the frequency of every character
        Dictionary<char, int> freq = new Dictionary<char, int>();
        foreach (char ch in s) {
            if (freq.ContainsKey(ch)) freq[ch]++;
            else freq[ch] = 1;
        }

        // Find the maximum frequency among all characters
        int maxFreq = freq.Values.Max();

        // Rearrangement is possible only if the maximum frequency
        // does not exceed ceil(n / 2)
        return maxFreq <= (n + 1) / 2;
    }

    static void Main() {
        string s = "aaabc";

        Console.WriteLine(canRearrange(s) ? "true" : "false");
    }
}
JavaScript
function canRearrange(s) {
    const n = s.length;

    // Count the frequency of every character
    const freq = new Map();
    for (const ch of s) {
        freq.set(ch, (freq.get(ch) || 0) + 1);
    }

    // Find the maximum frequency among all characters
    let maxFreq = 0;
    for (const val of freq.values()) {
        maxFreq = Math.max(maxFreq, val);
    }

    // Rearrangement is possible only if the maximum frequency
    // does not exceed ceil(n / 2)
    return maxFreq <= Math.floor((n + 1) / 2);
}

// Driver Code
const s = "aaabc";

console.log(canRearrange(s) ? "true" : "false");

Output
true

[Expected Approach] Using Boyer-Moore Voting Algorithm - O(n) Time and O(1) Space

The idea is to find a candidate for the most frequent character using Boyer-Moore's voting algorithm, then verify its actual count in a second pass. If that count exceeds ⌈n/2⌉, rearrangement is impossible; otherwise, it's always achievable.

Step by Step Implementation:

  • Run Boyer-Moore's voting algorithm: maintain a candidate and a count, incrementing the count when the current character matches the candidate, decrementing otherwise, and switching candidates whenever the count drops to zero.
  • After the voting phase, count how many times the resulting candidate actually appears in the string.
  • Check if this count exceeds ⌈n/2⌉ (computed as (n + 1) / 2 using integer division).
  • Return false if it does, true otherwise.
C++
#include <iostream>
#include <string>
using namespace std;

bool canRearrange(string &s) {
    int n = s.size();

    // Voting phase: find a candidate using Boyer-Moore's algorithm
    char candidate = '\0';
    int count = 0;
    for (char ch : s) {
        if (count == 0) {
            candidate = ch;
            count = 1;
        } else if (ch == candidate) {
            count++;
        } else {
            count--;
        }
    }

    // Verification phase: count the candidate's actual occurrences
    count = 0;
    for (char ch : s) {
        if (ch == candidate) {
            count++;
        }
    }

    // Rearrangement is impossible only if some character's frequency
    // exceeds ceil(n / 2)
    return count <= (n + 1) / 2;
}

int main() {
    string s = "aaabc";

    cout << (canRearrange(s) ? "true" : "false") << endl;
    return 0;
}
Java
class GFG {
    static boolean canRearrange(String s) {
        int n = s.length();

        // Voting phase: find a candidate using Boyer-Moore's algorithm
        char candidate = '\0';
        int count = 0;
        for (char ch : s.toCharArray()) {
            if (count == 0) {
                candidate = ch;
                count = 1;
            } else if (ch == candidate) {
                count++;
            } else {
                count--;
            }
        }

        // Verification phase: count the candidate's actual occurrences
        count = 0;
        for (char ch : s.toCharArray()) {
            if (ch == candidate) {
                count++;
            }
        }

        // Rearrangement is impossible only if some character's frequency
        // exceeds ceil(n / 2)
        return count <= (n + 1) / 2;
    }

    public static void main(String[] args) {
        String s = "aaabc";

        System.out.println(canRearrange(s));
    }
}
Python
def canRearrange(s):
    n = len(s)

    # Voting phase: find a candidate using Boyer-Moore's algorithm
    candidate = None
    count = 0
    for ch in s:
        if count == 0:
            candidate = ch
            count = 1
        elif ch == candidate:
            count += 1
        else:
            count -= 1

    # Verification phase: count the candidate's actual occurrences
    count = 0
    for ch in s:
        if ch == candidate:
            count += 1

    # Rearrangement is impossible only if some character's frequency
    # exceeds ceil(n / 2)
    return count <= (n + 1) // 2


s = "aaabc"

print("true" if canRearrange(s) else "false")
C#
using System;

class GFG {
    static bool canRearrange(string s) {
        int n = s.Length;

        // Voting phase: find a candidate using Boyer-Moore's algorithm
        char candidate = '\0';
        int count = 0;
        foreach (char ch in s) {
            if (count == 0) {
                candidate = ch;
                count = 1;
            } else if (ch == candidate) {
                count++;
            } else {
                count--;
            }
        }

        // Verification phase: count the candidate's actual occurrences
        count = 0;
        foreach (char ch in s) {
            if (ch == candidate) {
                count++;
            }
        }

        // Rearrangement is impossible only if some character's frequency
        // exceeds ceil(n / 2)
        return count <= (n + 1) / 2;
    }

    static void Main() {
        string s = "aaabc";

        Console.WriteLine(canRearrange(s) ? "true" : "false");
    }
}
JavaScript
function canRearrange(s) {
    const n = s.length;

    // Voting phase: find a candidate using Boyer-Moore's algorithm
    let candidate = null;
    let count = 0;
    for (const ch of s) {
        if (count === 0) {
            candidate = ch;
            count = 1;
        } else if (ch === candidate) {
            count++;
        } else {
            count--;
        }
    }

    // Verification phase: count the candidate's actual occurrences
    count = 0;
    for (const ch of s) {
        if (ch === candidate) {
            count++;
        }
    }

    // Rearrangement is impossible only if some character's frequency
    // exceeds ceil(n / 2)
    return count <= Math.floor((n + 1) / 2);
}

// Driver Code
const s = "aaabc";

console.log(canRearrange(s) ? "true" : "false");

Output
true
Comment