Sort Colors (LeetCode 75)
You have an array nums of n objects, each colored red, white, or blue. Rearrange them in-place so same-colored objects sit next to each other, ordered red, then white, then blue.
The colors are encoded as integers: 0 for red, 1 for white, and 2 for blue.
You may not call a built-in sort function to solve this.
Worked Examples
nums = [2,0,2,1,1,0][0,0,1,1,2,2]nums = [2,0,1][0,1,2]0, one 1 and one 2, arranged red, white, blue.⚖️Formal Constraints & Bounds
n == nums.length1 <= n <= 300nums[i]is either0,1, or2.
Core Insight
By maintaining three pointers (low for 0-boundary, mid for unexamined elements, and high for 2-boundary), each element is placed into its correct region in a single pass without needing extra memory.
Real-World Scenario & Production Applications
Three-way quicksort partitioning, multi-category triage buffers, and hardware memory tiering.
Subproblems & Recurrence Decomposition3 Phases
low marks the boundary of the 0-region, mid scans unexamined elements, and high marks the boundary of the 2-region. Everything before low is 0, everything after high is 2, and mid walks the unknown middle.
low, mid, high = 0, 0, len(nums) - 1Step-by-Step Execution Trace Table
| Step | low | mid | high | nums[mid] | Action | nums State |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 5 | 2 | nums[mid]==2 swap with high, high-- | [0, 0, 2, 1, 1, 2] |
| 1 | 0 | 0 | 4 | 0 | nums[mid]==0 swap with low, low++, mid++ | [0, 0, 2, 1, 1, 2] |
| 2 | 1 | 1 | 4 | 0 | nums[mid]==0 swap with low, low++, mid++ | [0, 0, 2, 1, 1, 2] |
| 3 | 2 | 2 | 4 | 2 | nums[mid]==2 swap with high, high-- | [0, 0, 1, 1, 2, 2] |
| 4 | 2 | 2 | 3 | 1 | nums[mid]==1 mid++ | [0, 0, 1, 1, 2, 2] |
| 5 | 2 | 3 | 3 | 1 | nums[mid]==1 mid++ | [0, 0, 1, 1, 2, 2] |
| End | 2 | 4 | 3 | — | mid > high loop terminates | [0, 0, 1, 1, 2, 2] |
| 1 | low, mid, high = 0, 0, len(nums) - 1 |
| 2 | while mid <= high: |
| 3 | if nums[mid] == 0: |
| 4 | swap(low, mid) |
| 5 | low += 1 |
| 6 | mid += 1 |
| 7 | elif nums[mid] == 1: |
| 8 | mid += 1 |
| 9 | else: |
| 10 | swap(mid, high) |
| 11 | high -= 1 |
| 12 | return nums |
Conceptual Narrative
🧭 Conceptual Foundation & Pattern Intuition
Move Zeroes partitioned elements into two regions (0 vs non-zero) using two pointers (reader and writer). In Sort Colors, there are three distinct categories (0, 1, and 2), requiring Dijkstra's Dutch National Flag algorithm with three pointers working in synergy.
🎨 The Analogy: A Three-Bin Conveyor Belt
Picture a conveyor belt carrying red (0), white (1), and blue (2) balls:
- At the far left sits the Red Bin (
lowpointer). - At the far right sits the Blue Bin (
highpointer). - The center zone between
lowandmidis reserved for White balls. - An inspector (
mid) examines each ball:- If Red (0): Toss it into the left bin (
swap(low, mid)), then advance bothlowandmid. (The item swapped fromlowis guaranteed to be 1, somidcan safely move on). - If White (1): It's already in the middle territory! Advance
mid. - If Blue (2): Toss it into the right bin (
swap(mid, high)), and decrementhigh. Crucial: Do NOT advancemid! The ball that just arrived fromhighwas unexamined—it might be red, white, or blue. You must inspect it on the next step.
- If Red (0): Toss it into the left bin (
Advancing
midpointer after swapping withhigh: Whennums[mid] == 2and you swap withnums[high], the incoming element atmidfromhighhas never been inspected (it could be 0, 1, or 2). You must decrementhighbut keepmidstationary.Terminating loop with
<instead of<=: The Dutch National Flag loop must executewhile mid <= high:. If you terminate atmid < high, the element athighis never inspected and remains unsorted.Swapping with
lowwithout advancing both pointers: Whennums[mid] == 0, swapping withnums[low]guarantees the incoming element atmidis1(becauselow <= midand all values beforemidare already 0 or 1). Thus bothlow += 1andmid += 1must advance.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Three-category partition + in-place requirement + single-pass constraint.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: nums[0..low-1] == 0, nums[low..mid-1] == 1, nums[high+1..n-1] == 2, with nums[mid..high] unexamined.
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
This problem's traps are in Common Pitfalls above.
The 60-Second Interview Pitch
Say this out loud before you type a single line
"I maintain three pointers: low, mid, and high. If nums[mid] is 0, I swap nums[low] and nums[mid], incrementing both low and mid. If nums[mid] is 1, I just increment mid. If nums[mid] is 2, I swap nums[mid] and nums[high] and decrement high without incrementing mid. Runs in
O(N)time andO(1)space."
Complexity & Mathematical Proof
O(N)
Look at the execution steps: Each iteration of the while loop either increments mid or decrements high. Since high - mid decreases by at least 1 at every step, the loop executes at most N times.
O(1) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Uses only three scalar pointer variables (low, mid, high) in-place.
T(N) = O(N)
Derivation Progression
Each iteration either advances mid by 1 (when 0 or 1) or retreats high by 1 (when 2).
At most one two-element swap and scalar increment/decrement per iteration.
The loop terminates when mid > high, guaranteeing at most N total iterations.
Variable Definitions
Total number of elements in the array
Memory Architecture & Bounds
O(1) Iterative
O(1) Three scalar pointers
O(1) In-place array modification
Boundary Best / Worst Cases
Pointer Invariant Transition Progression
Senior SWE Deconstruction & Hardware Caveats
Triggers: "sort array with 0s, 1s, 2s", "in-place", "one-pass algorithm using O(1) space". Dutch National Flag (Dijkstra) 3-way partition: partitions array into three distinct contiguous segments in a single pass.
, values . Single-pass time with auxiliary memory.
THE CRITICAL TRAP: Incrementing mid after swapping with high! When swapping nums[mid] with nums[high], the element brought in from high was previously uninspected; mid must NOT advance, allowing the next iteration to evaluate it. Conversely, swapping with low is guaranteed to bring in a 1 (since [low..mid-1] is all 1s), so advancing both low and mid is strictly safe.
Sort Colors (LeetCode 75)
You have an array nums of n objects, each colored red, white, or blue. Rearrange them in-place so same-colored objects sit next to each other, ordered red, then white, then blue.
The colors are encoded as integers: 0 for red, 1 for white, and 2 for blue.
You may not call a built-in sort function to solve this.
Worked Examples
nums = [2,0,2,1,1,0][0,0,1,1,2,2]nums = [2,0,1][0,1,2]0, one 1 and one 2, arranged red, white, blue.⚖️Formal Constraints & Bounds
n == nums.length1 <= n <= 300nums[i]is either0,1, or2.
Core Insight
By maintaining three pointers (low for 0-boundary, mid for unexamined elements, and high for 2-boundary), each element is placed into its correct region in a single pass without needing extra memory.
Real-World Scenario & Production Applications
Three-way quicksort partitioning, multi-category triage buffers, and hardware memory tiering.
Subproblems & Recurrence Decomposition3 Phases
low marks the boundary of the 0-region, mid scans unexamined elements, and high marks the boundary of the 2-region. Everything before low is 0, everything after high is 2, and mid walks the unknown middle.
low, mid, high = 0, 0, len(nums) - 1Step-by-Step Execution Trace Table
| Step | low | mid | high | nums[mid] | Action | nums State |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 5 | 2 | nums[mid]==2 swap with high, high-- | [0, 0, 2, 1, 1, 2] |
| 1 | 0 | 0 | 4 | 0 | nums[mid]==0 swap with low, low++, mid++ | [0, 0, 2, 1, 1, 2] |
| 2 | 1 | 1 | 4 | 0 | nums[mid]==0 swap with low, low++, mid++ | [0, 0, 2, 1, 1, 2] |
| 3 | 2 | 2 | 4 | 2 | nums[mid]==2 swap with high, high-- | [0, 0, 1, 1, 2, 2] |
| 4 | 2 | 2 | 3 | 1 | nums[mid]==1 mid++ | [0, 0, 1, 1, 2, 2] |
| 5 | 2 | 3 | 3 | 1 | nums[mid]==1 mid++ | [0, 0, 1, 1, 2, 2] |
| End | 2 | 4 | 3 | — | mid > high loop terminates | [0, 0, 1, 1, 2, 2] |
| 1 | low, mid, high = 0, 0, len(nums) - 1 |
| 2 | while mid <= high: |
| 3 | if nums[mid] == 0: |
| 4 | swap(low, mid) |
| 5 | low += 1 |
| 6 | mid += 1 |
| 7 | elif nums[mid] == 1: |
| 8 | mid += 1 |
| 9 | else: |
| 10 | swap(mid, high) |
| 11 | high -= 1 |
| 12 | return nums |
Conceptual Narrative
🧭 Conceptual Foundation & Pattern Intuition
Move Zeroes partitioned elements into two regions (0 vs non-zero) using two pointers (reader and writer). In Sort Colors, there are three distinct categories (0, 1, and 2), requiring Dijkstra's Dutch National Flag algorithm with three pointers working in synergy.
🎨 The Analogy: A Three-Bin Conveyor Belt
Picture a conveyor belt carrying red (0), white (1), and blue (2) balls:
- At the far left sits the Red Bin (
lowpointer). - At the far right sits the Blue Bin (
highpointer). - The center zone between
lowandmidis reserved for White balls. - An inspector (
mid) examines each ball:- If Red (0): Toss it into the left bin (
swap(low, mid)), then advance bothlowandmid. (The item swapped fromlowis guaranteed to be 1, somidcan safely move on). - If White (1): It's already in the middle territory! Advance
mid. - If Blue (2): Toss it into the right bin (
swap(mid, high)), and decrementhigh. Crucial: Do NOT advancemid! The ball that just arrived fromhighwas unexamined—it might be red, white, or blue. You must inspect it on the next step.
- If Red (0): Toss it into the left bin (
Advancing
midpointer after swapping withhigh: Whennums[mid] == 2and you swap withnums[high], the incoming element atmidfromhighhas never been inspected (it could be 0, 1, or 2). You must decrementhighbut keepmidstationary.Terminating loop with
<instead of<=: The Dutch National Flag loop must executewhile mid <= high:. If you terminate atmid < high, the element athighis never inspected and remains unsorted.Swapping with
lowwithout advancing both pointers: Whennums[mid] == 0, swapping withnums[low]guarantees the incoming element atmidis1(becauselow <= midand all values beforemidare already 0 or 1). Thus bothlow += 1andmid += 1must advance.
4-Phase Thought Process Model
Pattern Recognition Signals
The 10-second spot
Three-category partition + in-place requirement + single-pass constraint.
Formulating the Predicate & Invariants
Turning intuition into a boolean rule
Invariant: nums[0..low-1] == 0, nums[low..mid-1] == 1, nums[high+1..n-1] == 2, with nums[mid..high] unexamined.
Silent Failure Traps & Edge Cases
Where confident candidates still lose points
This problem's traps are in Common Pitfalls above.
The 60-Second Interview Pitch
Say this out loud before you type a single line
"I maintain three pointers: low, mid, and high. If nums[mid] is 0, I swap nums[low] and nums[mid], incrementing both low and mid. If nums[mid] is 1, I just increment mid. If nums[mid] is 2, I swap nums[mid] and nums[high] and decrement high without incrementing mid. Runs in
O(N)time andO(1)space."
Complexity & Mathematical Proof
O(N)
Look at the execution steps: Each iteration of the while loop either increments mid or decrements high. Since high - mid decreases by at least 1 at every step, the loop executes at most N times.
O(1) Auxiliary
Look at memory allocations: Call stack uses O(1) Iterative. Uses only three scalar pointer variables (low, mid, high) in-place.
T(N) = O(N)
Derivation Progression
Each iteration either advances mid by 1 (when 0 or 1) or retreats high by 1 (when 2).
At most one two-element swap and scalar increment/decrement per iteration.
The loop terminates when mid > high, guaranteeing at most N total iterations.
Variable Definitions
Total number of elements in the array
Memory Architecture & Bounds
O(1) Iterative
O(1) Three scalar pointers
O(1) In-place array modification
Boundary Best / Worst Cases
Pointer Invariant Transition Progression
Senior SWE Deconstruction & Hardware Caveats
Triggers: "sort array with 0s, 1s, 2s", "in-place", "one-pass algorithm using O(1) space". Dutch National Flag (Dijkstra) 3-way partition: partitions array into three distinct contiguous segments in a single pass.
, values . Single-pass time with auxiliary memory.
THE CRITICAL TRAP: Incrementing mid after swapping with high! When swapping nums[mid] with nums[high], the element brought in from high was previously uninspected; mid must NOT advance, allowing the next iteration to evaluate it. Conversely, swapping with low is guaranteed to bring in a 1 (since [low..mid-1] is all 1s), so advancing both low and mid is strictly safe.