Example 1
ready- Input
nums = [ 2, 0, 2, 1, 1, 0 ]- Expected
[ 0, 0, 1, 1, 2, 2 ]- Why
- equal colors group together in 0, 1, 2 order
Three paint colors have spilled into one row of cans. Each can is labeled 0, 1,
or 2, and you need the labels grouped in that order.
Given an integer array nums containing only 0, 1, and 2, return the
array sorted with every 0 first, then every 1, then every 2.
Think of 0 as red, 1 as white, and 2 as blue. The names add a story;
the numeric order decides the result.
A few ground rules:
1 <= nums.length <= 100_000nums[i] ∈ {0, 1, 2}Hints
Since there are only three possible values, you can count each one and overwrite the array with the right number of zeroes, ones, and twos.
Track a finished 0 region on the left, an unknown region in the middle, and a
finished 2 region on the right. Values between the left boundary and your
scanner are the finished 1 region.
When the scanner finds 2, swap it with the right boundary and shrink that
boundary. Don't advance the scanner yet: the value arriving from the right hasn't
been classified.
Can you finish in one pass without calling a general-purpose sorting routine?
Visible cases
nums = [
2,
0,
2,
1,
1,
0
][
0,
0,
1,
1,
2,
2
]nums = [
2,
2,
2
][
2,
2,
2
]nums = [
2,
0,
1
][
0,
1,
2
]Interview signal
Only three values can appear, so a general-purpose sort is unnecessary. Count each color, then overwrite the array in color order.
def sort_colors(nums: list[int]) -> list[int]:
counts = [0, 0, 0]
for color in nums:
counts[color] += 1
write = 0
for color, count in enumerate(counts):
for _ in range(count):
nums[write] = color
write += 1
return numsThis is already fast and uses no second n-sized array. Its one weakness is structural: it needs one pass to count and another to rebuild.
Time O(n) — two linear passes. Space O(1) — exactly three counters.
The Dutch national flag partition is a one-pass method that keeps three value groups and one not-yet-classified region. Use three indices:
low: the next position for a 0.mid: the value you're classifying now.high: the next position for a 2.Before each step, positions before low are zeroes, positions from low to
mid - 1 are ones, and positions after high are twos. Everything from
mid through high is still unknown.
def sort_colors(nums: list[int]) -> list[int]:
low = 0
mid = 0
high = len(nums) - 1
while mid <= high:
if nums[mid] == 0:
nums[low], nums[mid] = nums[mid], nums[low]
low += 1
mid += 1
elif nums[mid] == 1:
mid += 1
else:
nums[mid], nums[high] = nums[high], nums[mid]
high -= 1
return numsThe 2 case is the trap. You shrink high but leave mid in place because the
value swapped in from the unknown region still needs inspection. In the 0 case, advancing
both pointers is safe: anything swapped from low came from the finished one-region.
Time O(n) — each step shrinks the unknown region. Space O(1) — only three indices.
LeetCode's version mutates the array in place and returns void; ours returns the resulting array so the judge can compare it.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
[ 0, 0, 1, 1, 2, 2 ]