Loading problems...
TL;DR: The optimal solution uses three pointers to partition the array into three distinct regions (0s, 1s, and 2s) in a single pass, swapping elements into their correct positions in-place.
The "Sort Colors" problem requires sorting an array nums containing n objects colored red, white, or blue. These colors are represented by the integers 0, 1, and 2, respectively. The goal is to sort the array in-place so that objects of the same color are adjacent, following the order red (0), white (1), and blue (2). This is a classic interview question often found in the LeetCode 75 study plan.
The constraints strictly forbid using the library's built-in sort function and suggest finding a one-pass algorithm using constant extra space.
A naive brute force approach would be to treat this as a generic sorting problem without leveraging the fact that there are only three distinct values. One might simply implement a standard sorting algorithm like Bubble Sort or use a library function (though prohibited by the problem statement for the optimal solution).
Another common sub-optimal approach is a two-pass "Counting Sort" logic:
count0 indices with 0, the next count1 indices with 1, etc.).Pseudo-code (Counting Approach):
textcount0 = 0, count1 = 0, count2 = 0 for x in nums: increment count of x index = 0 for i from 0 to count0: nums[index++] = 0 for i from 0 to count1: nums[index++] = 1 for i from 0 to count2: nums[index++] = 2
Complexity Analysis:
Why it fails: While the counting approach is technically , it requires two passes over the data. The problem's follow-up explicitly asks for a one-pass algorithm. Furthermore, generic sorting does not utilize the limited cardinality of the input elements (only 3 values).
The key intuition for solving LeetCode 75 efficiently lies in partitioning the array into three sections. Instead of sorting by comparison, we place elements into their respective "buckets" relative to the array indices.
We can maintain three regions within the array using pointers:
0s.2s.1s and unprocessed elements.To implement this, we need three pointers:
low: The boundary for 0s. All elements before this index are 0.high: The boundary for 2s. All elements after this index are 2.mid: The current element being evaluated.The algorithm maintains the invariant that at any point during execution:
nums[0...low-1] are all 0s.nums[high+1...n-1] are all 2s.nums[low...mid-1] are all 1s.As mid traverses the array, we examine nums[mid] and swap it into the correct region (low or high) or leave it in the middle if it is a 1. This effectively shrinks the unknown region until the entire array is sorted.

Consider nums = [2, 0, 2, 1, 1, 0].
Start: low=0, mid=0, high=5.
nums[mid] is 2.nums[0] and nums[5]. Array: [0, 0, 2, 1, 1, 2].high to 4. mid stays 0.Step 2: low=0, mid=0, high=4.
nums[mid] is 0.nums[0] and nums[0] (self-swap). Array: [0, 0, 2, 1, 1, 2].low to 1, mid to 1.Step 3: low=1, mid=1, high=4.
nums[mid] is 0.nums[1] and nums[1]. Array: [0, 0, 2, 1, 1, 2].low to 2, mid to 2.Step 4: low=2, mid=2, high=4.
nums[mid] is 2.nums[2] and nums[4]. Array: [0, 0, 1, 1, 2, 2].high to 3. mid stays 2.Step 5: low=2, mid=2, high=3.
nums[mid] is 1.mid to 3.Step 6: low=2, mid=3, high=3.
nums[mid] is 1.mid to 4.End: mid (4) > high (3). Loop terminates. Result: [0, 0, 1, 1, 2, 2].
The correctness relies on the loop invariant involving the three partitions.
[0, low) contains 0s, (high, n-1] contains 2s, and [low, mid) contains 1s.0, we swap it to low, extending the 0s range and shifting the 1s range.1, we extend the 1s range by moving mid.2, we swap it to high, extending the 2s range.mid increases or high decreases at every step, the unclassified window [mid, high] shrinks to zero. When the loop finishes, the entire array is covered by the three sorted partitions.cppclass Solution { public: void sortColors(vector<int>& nums) { int low = 0; int mid = 0; int high = nums.size() - 1; while (mid <= high) { if (nums[mid] == 0) { // Swap current element to the 0s boundary swap(nums[low], nums[mid]); low++; mid++; } else if (nums[mid] == 1) { // 1s are in the middle, just move forward mid++; } else { // Swap current element to the 2s boundary swap(nums[mid], nums[high]); high--; // Do not increment mid; we need to check the swapped value } } } };
javaclass Solution { public void sortColors(int[] nums) { int low = 0; int mid = 0; int high = nums.length - 1; while (mid <= high) { if (nums[mid] == 0) { int temp = nums[low]; nums[low] = nums[mid]; nums[mid] = temp; low++; mid++; } else if (nums[mid] == 1) { mid++; } else { int temp = nums[high]; nums[high] = nums[mid]; nums[mid] = temp; high--; // Note: mid is NOT incremented here } } } }
pythonclass Solution: def sortColors(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ low, mid, high = 0, 0, 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] == 2 nums[high], nums[mid] = nums[mid], nums[high] high -= 1 # Do not increment mid here
low, mid, high) regardless of the input size.The "Two Pointers - In-place Array Modification" pattern is highly versatile. Understanding how to partition arrays using pointers is essential for the following problems:
0s and non-0s.Why do I get a wrong answer when swapping 2s?
mid immediately after swapping nums[mid] with nums[high].nums[high] is unknown. It could be a 0 or a 2 that needs further processing.0, it will be left in the middle of the array (the 1s region) incorrectly.Why does the loop terminate early?
mid < high instead of mid <= high as the loop condition.mid and high point to the same element, that element still needs to be evaluated.2s region might remain unsorted.Can I just overwrite the array?