Custom Comparators
What is this?
Sometimes "smallest to largest" isn't the order you want. A comparator is a little rule you hand the sort that, for any two items, says which one comes first. With the right rule you can order by frequency, by a made-up alphabet, or by which pairing forms the biggest number โ and the sort handles the rest.
๐ก Fun fact: Telling a sort what to compare instead of writing the sort yourself is why one well-chosen comparator can turn a hard interview problem into a single line of code.
๐ The 4 problems in this chapter are free. Sign in with Google or Microsoft to start solving.
Core idea: Sorting isn't only "smallest to largest." When the right order is some other rule โ biggest concatenation, highest frequency, a made-up alphabet โ you hand the sort a custom comparator (or a custom key) that says, for any two items, which comes first. Get that pairwise rule right and the library sort does the rest in O(n log n).
The pattern
A comparator answers one question: given items a and b, which goes first? The trick is choosing the comparison that makes the global arrangement come out right. Sometimes the key is a transformed value (frequency, then value as a tie-break). Sometimes it's a direct pairwise test โ comparing
a+bagainstb+ainstead of the numbers themselves. When the ordering is by count, you often skip the comparator entirely and bucket by count, reading buckets back in the order you want. And to verify an order rather than produce one, replace each element by its rank in the target order and check the sequence is non-decreasing.
The problems
- Largest Number โ sort the numbers as strings with the pairwise rule "a before b if
a+b>b+a"; concatenate the result. The clever comparator sidesteps a tricky greedy argument. - Sort Array by Increasing Frequency โ count occurrences, then sort by frequency ascending, breaking ties by value descending. A two-key comparator.
- Sort Characters By Frequency โ tally each character, then bucket by count and emit characters from high-count buckets to low; build the output string.
- Verifying an Alien Dictionary โ build a rank map from the alien alphabet, then check each adjacent word pair is in order under that ranking (with the prefix edge case).
Key takeaways
- A comparator is just a pairwise "who's first?" rule โ pick the one that makes the whole order correct.
- Multi-key sorting chains tie-breakers (frequency, then value) into one comparator.
- Bucket by count when the order is purely by frequency โ often beating a comparator outright.
- To verify an order, map to ranks and check the sequence is monotonic.
- Why it matters: real data rarely sorts by its raw value โ custom orderings are the everyday tool.
Order: Largest Number โ Sort Array by Increasing Frequency โ Sort Characters By Frequency โ Verifying an Alien Dictionary.
Largest Number
Core idea: You're given non-negative integers and must paste them together, in some order, into the largest possible number. The trap is that no simple sort key works โ not numeric value, not length. The right question for any two numbers
aandbis purely local: which placement,aborba, reads bigger? So compare them as strings:acomes beforebif and only ifa + b > b + a(string concatenation). Sort the whole list by that pairwise comparator, glue the pieces together, and you have the answer โ O(n log n ยท L) whereLis the length of the longest number. One last gotcha: if everything is zero, the join is"000...", which must collapse to"0".
The problem, rephrased
You run a "world-record number" booth at a fair. People hand you tiles, each stamped with a non-negative integer, and you must line the tiles up in a single row so the digits read off as the biggest number physically possible. You can reorder the tiles however you like, but you cannot break a tile apart or flip its digits. Return the row as a string (the number can be hundreds of digits long โ far too big for a normal integer).
This is LeetCode 179 โ Largest Number.
| Input | Means | Output |
|---|---|---|
nums = [10, 2] |
two tiles: 10 and 2 |
"210" |
nums = [3, 30, 34, 5, 9] |
five tiles | "9534330" |
nums = [0, 0] |
two zero tiles | "0" |
The output is a string, not an int โ both because the value can overflow and because the all-zeros case ("0") needs deliberate handling.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson