Sort Characters by Frequency: Heap or Buckets
This one is a Medium-rated classic reported from Amazon, Bloomberg, Zoom interviews: "Sort Characters by Frequency". Like every post in this series, the goal is not memorizing the answer — it is recognizing the Top-K and Heaps pattern on sight. Part 6 of 11 in the Top-K and Heaps arc.
The Problem
Given a string, return it sorted by character frequency, descending; characters with equal counts may appear in any relative order. Unlike Top-K questions, every group is output — which changes which tool is optimal, and noticing that is the point.
Input: s = "tree"
Output: "eert" (or "eetr")
Recognizing the Top-K and Heaps Pattern
When a problem asks for the k largest, smallest, closest, or most frequent — or for repeated access to an extreme while data changes — a heap gives O(log n) insertion and O(1) access to the extreme. The signature trick: keep a bounded heap of size k with the opposite polarity (a min-heap to track the k largest), evicting the root on overflow. Python's heapq is a min-heap; negate values for max behavior.
Full ordering by frequency, not selection of k — so the bounded-heap trick buys nothing. A max-heap over all distinct characters is the natural fit; counts bounded by the string length also admit bucket grouping at O(n). Choosing tools by what the output actually requires is the meta-skill here.
The Approach
Count. Push (−count, char) for each distinct character; pop in order, appending each character repeated count times. With at most 62 alphanumerics (or any fixed alphabet) the heap is effectively O(1) — the real cost is building the output.
''.join over accumulated pieces, never += in a loop — string concatenation in a loop is quadratic and is a known silent performance flag in Python screens.
Python Solution
import heapq
from collections import Counter
def frequency_sort(s: str) -> str:
"""Characters ordered by descending frequency."""
counts = Counter(s)
heap = [(-count, ch) for ch, count in counts.items()]
heapq.heapify(heap)
pieces: list[str] = []
while heap:
count, ch = heapq.heappop(heap)
pieces.append(ch * (-count))
return "".join(pieces)
Complexity
- Time: O(n + d log d) — counting is O(n); heap work is over d distinct characters
- Space: O(n) — counts and the output
Interview Tips and Follow-Ups
- Case sensitivity is specified ('A' differs from 'a') — restate it; assumed case-folding is a quiet correctness bug.
counter.most_common()sorts for you — fine to use if you state it is O(d log d) under the hood; hiding behind stdlib without knowing costs is the anti-signal.- Bridge question: this plus a max-heap with cooldown becomes Task Scheduler and Reorganize String — the next two posts. Frequency plus greedy is a mini-pattern.
If this clicked, continue the Top-K and Heaps arc in the Technical Interview category. One hundred questions, nine patterns, all in Python.
Keep reading
Find Median From a Data Stream With Two Heaps
The two-heap balance: max-heap low half, min-heap high half. Python solution and complexity analysis for the heap and top-k interview pattern.
K Closest Points to Origin Without Square Roots
Bounded max-heap on squared distance — monotone transforms are free. Python solution and complexity analysis for the heap and top-k interview pattern.
Find K Pairs With Smallest Sums: Frontier Expansion
Explore an implicit sorted matrix — seed one row, expand neighbors lazily. Python solution and complexity analysis for the heap and top-k interview pattern.
Newsletter
New posts, straight to your inbox
One email per post. No spam, no tracking pixels, unsubscribe anytime.
Comments
- No comments yet. Be the first.