You are given the head of a singly linked list whose every node holds one of just three values — 0, 1, or 2. Rearrange the list in place so that all the 0s come first, then all the 1s, and finally all the 2s. Return the head of the rearranged list.
The relative order among equal values does not matter — only that the three groups end up in the order 0s, then 1s, then 2s.
Input: head = [1, 2, 2, 1, 2, 0, 2, 2] Output: [0, 1, 1, 2, 2, 2, 2, 2] Every 0 is pulled to the front, every 2 pushed to the back, and the 1s settle in between.
Input: head = [2, 2, 0, 1] Output: [0, 1, 2, 2] The single 0 leads, the 1 follows, and both 2s trail at the end.
- 1 <= number of nodes <= 10^6 - 0 <= node value <= 2
A list of only three distinct values is a special gift: you never have to compare anything. Let's go from the obvious sort to a single-pass rewire that touches each node exactly once.
null.next pointers rather than copying node data.In plain words: the values 0, 1, 2 are their own sort keys. Formally, partition the nodes into three groups by value and concatenate them in the order 0-group, 1-group, 2-group.
Worked example — head = 1 → 2 → 2 → 1 → 2 → 0 → 2 → 2
bucket 0: 0 bucket 1: 1 → 1 bucket 2: 2 → 2 → 2 → 2 → 2 glue in order 0,1,2: 0 → 1 → 1 → 2 → 2 → 2 → 2 → 2
Asking two sharp questions before coding shows you read the guarantees instead of assuming them — that is what separates a senior candidate from someone who dives straight in.
“Are the values strictly limited to 0, 1, and 2?”
If a stray 3 can appear, counting into three buckets silently drops it — I would need a general sort instead.
“Can the list be a single node, or already sorted?”
Both must pass untouched; the relinking must not create a cycle or lose the tail.
“How large can the list get?”
At 10^6 nodes an O(n log n) comparison sort is wasteful — the three-value structure lets me do a single O(n) pass.
Before I code, let me confirm the guarantees.
First — are the node values always exactly 0, 1, or 2, with nothing else possible?
And finally — a single node or an already-sorted list should return unchanged, correct?
A comparison sort asks "is a before b?" over and over. But here the answer is free: a 0 always precedes a 1 which always precedes a 2. So you can just count how many of each you have and lay them down in order — no comparisons at all.
Instead of overwriting each node's value, keep three growing sublists and append each node to the one matching its value. This never touches the payload, which matters when nodes carry more than an integer.
zero: 0-dummy → …0 nodes… one: 1-dummy → …1 nodes… two: 2-dummy → …2 nodes… stitch: zero-tail → one-head → two-head
The pointer method visits each node once, deciding its bucket on the spot. Counting needs two passes (tally, then rewrite). Both are O(n), but the single-pass rewire is the tightest and never mutates data.
| Collect & sort | Count & rewrite | Three lists (relink) | |
|---|---|---|---|
| Time | O(n log n) | O(n) | O(n) |
| Space | O(n) | O(1) | O(1) |
| Passes | 2 | 2 | 1 |
| Mutates data |
The full code for each approach lives in the Approaches selector below.
Key takeaway
When the universe of values is tiny and fixed, throw away comparisons: bucket by value and concatenate. On a linked list you can bucket by relinking, giving an O(n) time, O(1) space, single-pass, data-preserving sort.
zeroTail, oneTail, twoTail ← three dummy heads
for each node in list:
append node to the tail matching node.value
stitch: zeroTail → oneHead → twoHead → null
return zeroDummy.next