Sort Colors (Dutch National Flag)
Given an array nums with n objects colored red, white, or blue (represented as 0, 1, or 2), sort them in-place so that objects of the same color are adjacent, with the colors in the order red (0), white (1), and blue (2). You must solve this without using the library's sort function.
- n == nums.length
- 1 <= n <= 300
- nums[i] is either 0, 1, or 2
- Come up with a one-pass algorithm using only constant extra space
nums = [2,0,2,1,1,0][0,0,1,1,2,2]nums = [2,0,1][0,1,2]nums = [1,1,1][1,1,1]Sorting an array with only three distinct values (0, 1, and 2) is a specialized challenge. While you could use a standard sorting algorithm, the fixed set of values allows us to be much more efficient. The goal is to group all identical numbers together in the order 0, 1, and 2 without using extra space.
One straightforward way to solve this is the Two-Pass Counting approach. In the first pass, we simply count how many zeros, ones, and twos exist in the array. In the second pass, we overwrite the original array with that many zeros, then that many ones, and finally the remaining twos.
# Two-Pass Counting (O(N) Time, O(1) Space)
counts = [0, 0, 0]
for x in nums:
counts[x] += 1
idx = 0
for color in range(3):
for _ in range(counts[color]):
nums[idx] = color
idx += 1While efficient, this requires two full passes. To solve the problem in a Single Pass, we use the Dutch National Flag algorithm. We imagine the array as three distinct regions: the "Red" zone (0s) at the front, the "Blue" zone (2s) at the back, and the "White" zone (1s) in the middle. We use three pointers to maintain these boundaries:
- low: Everything to the left of this pointer is a confirmed 0.
- high: Everything to the right of this pointer is a confirmed 2.
- mid: The explorer that inspects every element from left to right.
The strategy works as follows:
- If we see a 0: Swap it with the low pointer and move both low and mid forward.
- If we see a 2: Swap it with the high pointer and move high backward. We do not move mid yet because we need to inspect the value that just arrived from the back.
- If we see a 1: Just move mid forward.
# One-Pass DNF (O(N) Time, O(1) Space)
low, mid = 0, 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] == 2:
nums[mid], nums[high] = nums[high], nums[mid]
high -= 1
else: # nums[mid] == 1
mid += 1Dutch National Flag
3-Way Partitioning with Pointers
Key Insight
We maintain three zones: [0, low-1] for 0s, [low, mid-1] for 1s, and [high+1, n-1] for 2s. mid explores the unknown.
One Pass Strategy
If mid finds a 0, swap with low and advance both. If 1, just advance mid. If 2, swap with high and shrink high only.