Sort Characters By Frequency

MediumHash Map · Bucket Sort🧩 Bucket & Counting SortLeetCode #451 ↗Updated

Problem

Rearrange the characters of string s so that characters appearing more often come first. All copies of the same character must sit next to each other. Characters are case-sensitive ('A' and 'a' differ), and when two characters tie, either order is accepted.
Inputs = "tree"Output"eert" ("eetr" also valid)
Inputs = "cccaaa"Output"cccaaa" ("aaaccc" also valid)
Inputs = "Aabb"Output"bbAa" ("bbaA" also valid)

1 ≤ s.length ≤ 5·105  ·  s has upper/lowercase English letters and digits

Try it yourself

Java
class Solution {
    public String frequencySort(String s) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
A frequency can never exceed n, so instead of sorting by count you can drop each character into bucket[count] and read the buckets from high to low — a counting sort on frequencies.
PatternBucket & Counting Sort

Instinct Keys live in a small, known range (letters, frequencies 1..n, bounded values) - index an array by the key instead of comparing, and get O(n).

Memory hack Don't compare, just file it - every value walks straight to its own pigeonhole, then you read the shelves in order.

Open the Bucket & Counting Sort guide →

Approaches

Brute ForceCount, then Sort Every Character

Time O(n log n)Space O(n)

Count frequencies, box all n characters and sort them with a comparator: higher count first, and for equal counts by the character itself so equal letters end up adjacent. Join the sorted characters.

Java
public String frequencySort(String s) {
    Map<Character, Integer> freq = new HashMap<>();
    for (char c : s.toCharArray()) freq.merge(c, 1, Integer::sum);
    Character[] chars = new Character[s.length()];
    for (int i = 0; i < chars.length; i++) chars[i] = s.charAt(i);
    // more frequent first; tie-break on the char keeps equal letters together
    Arrays.sort(chars, (x, y) -> {
        int fx = freq.get(x), fy = freq.get(y);
        return fx != fy ? fy - fx : x - y;
    });
    StringBuilder sb = new StringBuilder();
    for (char c : chars) sb.append(c);
    return sb.toString();
}

Direct, but sorts n boxed characters when only a few distinct ones exist.

At a glance

LevelApproachTimeSpace
Brute ForceCount, then Sort Every CharacterO(n log n)O(n)
BetterCount + Max-Heap of Distinct CharactersO(n + k log k)O(n + k)
OptimalBucket Sort by FrequencyO(n)O(n)
Common pitfalls
  • Treating 'A' and 'a' as the same character.
  • Sorting only by count without a tie-break — equal-count letters can interleave ("abab").
  • Building the result with += on a String — O(n2) copying.
Interview tips
  • Ask about the character set: a fixed 128-slot array beats a hash map.
  • Note that only k distinct chars need ordering, which motivates the heap.
  • Point out frequencies are bounded by n — that bound is what enables bucket sort.
Pattern
Count + bucket by frequency → order items by how often they occur in O(n).
My notes saved in this browser