Problem
Given a string, rearrange its characters so that the most frequent character appears first. Among characters with equal frequency any ordering is valid, and the same character letter in different cases ('A' vs 'a') counts as two distinct characters.
- Input:
s = "tree" - Output:
"eert" - Explanation:
'e'appears twice and leads the output;'t'and'r'each appear once and can follow in any order.
A useful counter-example showing case sensitivity: in "Aabb", 'A' and 'a' are separate characters each with frequency 1, while 'b' has frequency 2.
- Input:
s = "Aabb" - Output:
"bbAa" - Explanation:
'b'appears twice;'A'and'a'are distinct and each appear once.
Intuition
Once you know each character's frequency, you just need to output characters in descending order of that count. The brute-force way is to sort characters by frequency โ simple and correct. A smarter observation: every character frequency must land between 1 and n, so you can skip comparison-based sorting entirely and use bucket sort to group characters by their exact frequency, achieving a true O(n) pass.
Approach 1 โ Frequency Map + Sort
Count each character's frequency, then sort the unique characters by frequency descending. Build the result by repeating each character by its count.
- Count frequencies with a hash map.
- Collect unique characters into a list.
- Sort the list by frequency descending.
- Concatenate each character repeated by its frequency.
1from collections import Counter
2
3class Solution:
4 def frequencySort(self, s: str) -> str:
5 freq = Counter(s)
6 # sort unique characters by their frequency, highest first
7 sorted_chars = sorted(freq, key=lambda c: -freq[c])
8 return ''.join(c * freq[c] for c in sorted_chars)Time: O(n log n) โ counting is O(n); sorting at most k unique characters is O(k log k), and k โค n.
Space: O(n) โ the frequency map and result string each hold at most n characters.
Approach 2 โ Bucket Sort
Since any character's frequency is between 1 and n, create an array of buckets indexed by frequency. Fill buckets by scanning the frequency map, then read them from highest to lowest to build the result โ no comparison-based sort needed.
- Count character frequencies.
- Create
n + 1buckets;buckets[i]holds every character that appears exactlyitimes. - Iterate buckets from index
ndown to1, appending each character repeated by its bucket index.
1from collections import Counter
2
3class Solution:
4 def frequencySort(self, s: str) -> str:
5 freq = Counter(s)
6
7 # index represents frequency; max possible frequency equals len(s)
8 buckets = [[] for _ in range(len(s) + 1)]
9 for char, count in freq.items():
10 buckets[count].append(char)
11
12 result = []
13 for count in range(len(s), 0, -1): # high frequency first
14 for char in buckets[count]:
15 result.append(char * count)
16 return ''.join(result)Time: O(n) โ counting is O(n), filling buckets is O(k) โค O(n), and reading buckets rebuilds at most n characters total.
Space: O(n) โ buckets and result together hold at most n characters.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Frequency Map + Sort | O(n log n) | O(n) | When simplicity matters; works for any sortable key |
| Bucket Sort | O(n) | O(n) | When the value range is bounded (character frequencies, small integers) |
Common Mistakes
-
Treating
'A'and'a'as the same character โ the problem is case-sensitive."Aabb"has frequencies{b:2, A:1, a:1}, not{b:2, a:2}. Normalizing to lowercase before counting produces a wrong answer. -
Bucket array sized
ninstead ofn + 1โ if a single character fills the entire string its frequency equalsn, requiring indexn. An array of sizenthrows an out-of-bounds error on that case. -
String concatenation inside a loop in Java โ
result += c.repeat(count)inside a loop creates a newStringobject on each iteration, making the build step O(nยฒ). Always useStringBuilder.append()or collect into a list and join once. -
Sorting ascending instead of descending โ omitting
reverse=Trueor using the wrong comparator sign puts the rarest characters first, which is the exact opposite of what the problem asks.
Related Problems
top-k-frequent-elementsโ same frequency map foundation; pick the top k by count instead of sorting all of themtop-k-frequent-wordsโ identical pattern with an added lexicographic tiebreaker for words of equal frequencyfirst-unique-character-in-a-stringโ frequency map to find the first character with count exactly 1reorganize-stringโ character frequency with the extra constraint that no two adjacent characters can be identicalfind-all-anagrams-in-a-stringโ sliding-window frequency map comparison to detect rearrangements