Bird
Raised Fist0
DSA Goprogramming~15 mins

Sort Colors Two Pointer Dutch Flag in DSA Go - Deep Dive

Choose your learning style10 modes available
Overview - Sort Colors Two Pointer Dutch Flag
What is it?
Sort Colors Two Pointer Dutch Flag is a method to sort an array containing only three different values, usually 0, 1, and 2, representing colors. It uses two pointers to rearrange the array in a single pass without extra space. This approach is efficient and easy to implement for sorting these three distinct elements.
Why it matters
Without this method, sorting such arrays might require multiple passes or extra memory, making the process slower and less efficient. This algorithm solves the problem quickly and in-place, which is important in real-world applications where performance and memory use matter, like image processing or organizing data by categories.
Where it fits
Before learning this, you should understand arrays and basic sorting concepts. After mastering this, you can explore more complex sorting algorithms and two-pointer techniques used in other problems like partitioning or searching.
Mental Model
Core Idea
Use two pointers to separate three groups by swapping elements in one pass, placing all 0s first, then 1s, then 2s.
Think of it like...
Imagine sorting red, white, and blue balls into three boxes by moving balls one by one, putting reds in the first box, blues in the last, and whites in the middle without extra space.
Start: [0,1,2,0,1,2]
Pointers: low=0, mid=0, high=5
Process:
[low]----[mid]----------------[high]
|       |                      |
0       0                      2

After swaps:
[0,0,1,1,2,2]
Positions:
low -> end of 0s
mid -> current element
high -> start of 2s
Build-Up - 7 Steps
1
FoundationUnderstanding the Problem Setup
šŸ¤”
Concept: Introduce the problem of sorting an array with only three distinct values: 0, 1, and 2.
We have an array like [2,0,2,1,1,0]. Our goal is to sort it so that all 0s come first, then all 1s, then all 2s. We only have these three values, so we don't need a full sorting algorithm. We want to do this efficiently.
Result
Recognize the problem as sorting three groups in one array.
Understanding the problem constraints helps us choose a specialized, efficient approach instead of general sorting.
2
FoundationBasics of Two Pointer Technique
šŸ¤”
Concept: Learn what two pointers are and how they can help traverse and modify arrays efficiently.
Two pointers are variables that point to positions in the array. We can move them to track where to place elements or to scan the array from different ends. For example, one pointer can track where to put 0s, another where to put 2s.
Result
Know how to use pointers to scan and rearrange arrays without extra space.
Knowing how pointers move and interact is key to in-place algorithms that save memory and time.
3
IntermediateIntroducing Three Pointers for Sorting
šŸ¤”Before reading on: do you think two pointers are enough to sort three groups, or do we need more? Commit to your answer.
Concept: Use three pointers: low, mid, and high to separate 0s, 1s, and 2s in one pass.
We use: - low: boundary for 0s - mid: current element - high: boundary for 2s We move mid through the array: - If nums[mid] == 0, swap with nums[low], move low and mid forward. - If nums[mid] == 1, just move mid forward. - If nums[mid] == 2, swap with nums[high], move high backward. This way, 0s go left, 2s go right, 1s stay in the middle.
Result
Array sorted in one pass with three pointers.
Understanding the role of each pointer clarifies how the array is partitioned dynamically.
4
IntermediateStep-by-Step Dry Run Example
šŸ¤”Before reading on: predict the array state after first swap if starting with [2,0,2,1,1,0]. Commit to your answer.
Concept: Walk through the algorithm on a sample array to see how pointers move and swaps happen.
Start: nums=[2,0,2,1,1,0], low=0, mid=0, high=5 - nums[mid]=2, swap nums[mid] and nums[high]: [0,0,2,1,1,2], high=4 - nums[mid]=0, swap nums[mid] and nums[low]: [0,0,2,1,1,2], low=1, mid=1 - nums[mid]=0, swap nums[mid] and nums[low]: [0,0,2,1,1,2], low=2, mid=2 - nums[mid]=2, swap nums[mid] and nums[high]: [0,0,1,1,2,2], high=3 - nums[mid]=1, mid=3 - nums[mid]=1, mid=4 End: [0,0,1,1,2,2]
Result
Sorted array: [0,0,1,1,2,2]
Dry runs reveal how the algorithm efficiently sorts with minimal swaps and pointer moves.
5
IntermediateGo Code Implementation Explained
šŸ¤”
Concept: Show the complete Go code for the algorithm with comments explaining each step.
package main import "fmt" func sortColors(nums []int) { low, mid, high := 0, 0, len(nums)-1 for mid <= high { switch nums[mid] { case 0: nums[low], nums[mid] = nums[mid], nums[low] low++ mid++ case 1: mid++ case 2: nums[mid], nums[high] = nums[high], nums[mid] high-- } } } func main() { nums := []int{2,0,2,1,1,0} sortColors(nums) fmt.Println(nums) // Output: [0 0 1 1 2 2] }
Result
[0 0 1 1 2 2]
Seeing the code with comments connects theory to practice and clarifies pointer updates and swaps.
6
AdvancedAlgorithm Efficiency and In-Place Sorting
šŸ¤”Before reading on: do you think this algorithm uses extra memory or sorts in-place? Commit to your answer.
Concept: Analyze time and space complexity and why in-place sorting matters.
The algorithm runs in O(n) time because it makes one pass through the array. It uses O(1) extra space because it only uses pointers and swaps elements in the original array. This is efficient for large data sets and important when memory is limited.
Result
Efficient sorting with minimal memory and time.
Knowing the algorithm's efficiency helps choose it for performance-critical applications.
7
ExpertHandling Variations and Edge Cases
šŸ¤”Before reading on: what happens if the array has no 0s or no 2s? Will the algorithm still work correctly? Commit to your answer.
Concept: Explore how the algorithm behaves with missing groups and how to adapt it if needed.
If the array lacks 0s or 2s, the pointers adjust naturally, and the algorithm still sorts correctly. For example, if no 0s, low and mid move forward without swaps. If input has other values, the algorithm must be adapted or validated. Also, the algorithm can be extended to sort other three-group problems by changing conditions.
Result
Robust sorting even with missing groups or variations.
Understanding edge cases ensures the algorithm is reliable and adaptable in real-world scenarios.
Under the Hood
The algorithm maintains three regions in the array: all elements before 'low' are 0s, elements between 'low' and 'mid' are 1s, and elements after 'high' are 2s. The 'mid' pointer scans elements, swapping 0s to the front and 2s to the back, shrinking the unsorted middle region. This in-place partitioning avoids extra memory and multiple passes.
Why designed this way?
This method was designed to solve the Dutch National Flag problem efficiently by Edsger Dijkstra. It avoids the overhead of counting or multiple scans by cleverly using pointers and swaps. Alternatives like counting sort use extra space or multiple passes, which are less optimal for this specific problem.
Array: [0s][1s][unknown][2s]
Pointers:
 low -> end of 0s
 mid -> current element
 high -> start of 2s

Process:
ā”Œā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”
│ 0s  │ 1s  │ unknown │ 2s  │
ā””ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”˜
  ↑     ↑       ↑       ↑
 low   mid     mid     high

mid moves right, swapping 0s left and 2s right, shrinking unknown.
Myth Busters - 3 Common Misconceptions
Quick: Does swapping a 2 with the element at 'high' always move 'mid' forward? Commit yes or no.
Common Belief:Swapping a 2 with the element at 'high' means we can move 'mid' forward immediately.
Tap to reveal reality
Reality:After swapping with 'high', 'mid' should not move forward immediately because the swapped element might be 0, 1, or 2 and needs to be checked.
Why it matters:Moving 'mid' forward too soon can skip elements, causing incorrect sorting or missed swaps.
Quick: Is it necessary to sort the array twice, once for 0s and once for 2s? Commit yes or no.
Common Belief:You must first move all 0s to the front, then move all 2s to the end in separate passes.
Tap to reveal reality
Reality:The Dutch Flag algorithm sorts all three groups in one pass using three pointers.
Why it matters:Doing multiple passes wastes time and is less efficient than the one-pass solution.
Quick: Can this algorithm sort arrays with more than three distinct values? Commit yes or no.
Common Belief:This algorithm works for any number of distinct values, not just three.
Tap to reveal reality
Reality:It only works efficiently for exactly three distinct values; more values require different algorithms.
Why it matters:Using it for more values leads to incorrect results or inefficient sorting.
Expert Zone
1
The order of pointer updates after swaps is critical; swapping 0s requires moving both 'low' and 'mid', but swapping 2s only moves 'high'.
2
The algorithm's in-place nature means it can be adapted for streaming data or memory-constrained environments.
3
Understanding that the algorithm partitions the array into three dynamic regions helps in extending it to similar partitioning problems.
When NOT to use
Avoid this algorithm when sorting arrays with more than three distinct values or when stability (preserving original order) is required. Use counting sort or comparison-based sorts like quicksort or mergesort instead.
Production Patterns
Used in image processing to sort pixels by color channels, in networking to prioritize packets by type, and in real-time systems where quick, in-place categorization is needed without extra memory overhead.
Connections
Partition step in Quicksort
Both use pointers to partition arrays into groups based on pivot values.
Understanding Dutch Flag partitioning clarifies how quicksort divides arrays efficiently.
Counting Sort
Both sort arrays with limited distinct values but counting sort uses extra space and multiple passes.
Knowing the tradeoff between in-place and counting methods helps choose the right algorithm for constraints.
Traffic Light Control Systems
Both categorize items into three groups and manage transitions between states.
Recognizing similar three-state partitioning in unrelated fields shows the universality of this pattern.
Common Pitfalls
#1Moving 'mid' pointer forward after swapping with 'high' without checking the swapped element.
Wrong approach:if nums[mid] == 2 { nums[mid], nums[high] = nums[high], nums[mid] high-- mid++ // wrong: mid should not move here }
Correct approach:if nums[mid] == 2 { nums[mid], nums[high] = nums[high], nums[mid] high-- // mid stays to check swapped element }
Root cause:Misunderstanding that the swapped element at 'mid' might be 0, 1, or 2 and needs processing.
#2Using two pointers instead of three, causing incorrect sorting of the middle group (1s).
Wrong approach:low, high := 0, len(nums)-1 for low < high { if nums[low] == 2 { nums[low], nums[high] = nums[high], nums[low] high-- } else { low++ } } // misses sorting 1s correctly
Correct approach:low, mid, high := 0, 0, len(nums)-1 for mid <= high { switch nums[mid] { case 0: nums[low], nums[mid] = nums[mid], nums[low] low++ mid++ case 1: mid++ case 2: nums[mid], nums[high] = nums[high], nums[mid] high-- } }
Root cause:Not accounting for the middle group requires a third pointer to track current position.
#3Assuming the algorithm is stable and preserves the order of equal elements.
Wrong approach:Using this algorithm expecting the relative order of 1s to remain the same.
Correct approach:Use a stable sorting algorithm like counting sort or mergesort if order preservation is needed.
Root cause:Misunderstanding that in-place swaps change element order and this algorithm is not stable.
Key Takeaways
The Dutch Flag algorithm sorts arrays with three distinct values efficiently in one pass using three pointers.
It works in-place with O(1) extra space and O(n) time, making it optimal for this problem.
Correct pointer movement and swap order are crucial to avoid skipping elements or incorrect sorting.
This method is specialized and should not be used for arrays with more than three distinct values or when stability is required.
Understanding this algorithm deepens knowledge of partitioning techniques used in many sorting and searching algorithms.

Practice

(1/5)
1. What is the main idea behind the Sort Colors Two Pointer Dutch Flag algorithm?
easy
A. Use three pointers to separate 0s, 1s, and 2s in one pass
B. Sort the array using bubble sort repeatedly
C. Count each color and then overwrite the array
D. Use recursion to sort colors

Solution

  1. Step 1: Understand the problem

    The algorithm sorts an array containing only 0s, 1s, and 2s representing colors.
  2. Step 2: Identify the approach

    It uses three pointers (low, mid, high) to place 0s at the start, 2s at the end, and 1s in the middle in one pass.
  3. Final Answer:

    Use three pointers to separate 0s, 1s, and 2s in one pass -> Option A
  4. Quick Check:

    Three pointers = One pass sorting [OK]
Hint: Remember three pointers separate colors in one pass [OK]
Common Mistakes:
  • Thinking it uses multiple passes like bubble sort
  • Confusing counting approach with two-pointer method
  • Assuming recursion is used
2. Which of the following Go code snippets correctly initializes the three pointers for the Dutch Flag algorithm?
easy
A. low, mid, high := 0, 0, len(nums)-1
B. low, mid, high := 0, len(nums)-1, 0
C. low, mid, high := len(nums)-1, 0, 0
D. low, mid, high := len(nums), 0, len(nums)-1

Solution

  1. Step 1: Identify pointer roles

    Low and mid start at 0, high starts at last index (len(nums)-1).
  2. Step 2: Match initialization

    low, mid, high := 0, 0, len(nums)-1 correctly sets low=0, mid=0, high=len(nums)-1.
  3. Final Answer:

    low, mid, high := 0, 0, len(nums)-1 -> Option A
  4. Quick Check:

    Pointers start at array ends and start [OK]
Hint: Start low and mid at 0, high at last index [OK]
Common Mistakes:
  • Swapping low and high initialization
  • Setting pointers outside array bounds
  • Confusing mid pointer position
3. What will be the output of the following Go code after applying the Dutch Flag algorithm?
nums := []int{2, 0, 2, 1, 1, 0}
low, mid, high := 0, 0, len(nums)-1
for mid <= high {
  switch nums[mid] {
  case 0:
    nums[low], nums[mid] = nums[mid], nums[low]
    low++
    mid++
  case 1:
    mid++
  case 2:
    nums[mid], nums[high] = nums[high], nums[mid]
    high--
  }
}
fmt.Println(nums)
medium
A. [0 1 0 1 2 2]
B. [0 0 1 1 2 2]
C. [2 2 1 1 0 0]
D. [1 1 0 0 2 2]

Solution

  1. Step 1: Trace the loop iterations

    Initially nums = [2,0,2,1,1,0], low=0, mid=0, high=5. The loop swaps 0s to front, 2s to end, 1s stay in middle.
  2. Step 2: Final sorted array

    After processing, nums becomes [0,0,1,1,2,2].
  3. Final Answer:

    [0 0 1 1 2 2] -> Option B
  4. Quick Check:

    Sorted colors = [0 0 1 1 2 2] [OK]
Hint: Swap 0s left, 2s right, 1s stay middle [OK]
Common Mistakes:
  • Not updating mid after swapping 0
  • Updating mid after swapping 2 incorrectly
  • Confusing order of swaps
4. Identify the bug in this Go code snippet implementing the Dutch Flag algorithm:
nums := []int{2,0,1}
low, mid, high := 0, 0, len(nums)-1
for mid < high {
  if nums[mid] == 0 {
    nums[low], nums[mid] = nums[mid], nums[low]
    low++
    mid++
  } else if nums[mid] == 2 {
    nums[mid], nums[high] = nums[high], nums[mid]
    high--
  } else {
    mid++
  }
}
fmt.Println(nums)
medium
A. Swapping 0s and 2s is done in wrong order
B. Pointers low and mid are initialized incorrectly
C. Loop condition should be mid <= high, not mid < high
D. The array is not initialized properly

Solution

  1. Step 1: Check loop condition

    The loop uses 'mid < high' but it should be 'mid <= high' to process all elements including when mid equals high.
  2. Step 2: Effect of wrong condition

    With 'mid < high', the last element may not be processed, causing incorrect sorting.
  3. Final Answer:

    Loop condition should be mid <= high, not mid < high -> Option C
  4. Quick Check:

    Loop must cover all elements [OK]
Hint: Use mid <= high to process all elements [OK]
Common Mistakes:
  • Using mid < high misses last element
  • Incorrect pointer initialization
  • Swapping logic errors
5. Given an array nums containing only 0s, 1s, and 2s, how would you modify the Dutch Flag algorithm to count the number of swaps performed during sorting?
hard
A. Count swaps after sorting by comparing original and sorted arrays
B. Swaps cannot be counted in this algorithm
C. Use recursion to count swaps automatically
D. Add a counter and increment it each time a swap occurs inside the loop

Solution

  1. Step 1: Understand swap points

    Swaps happen when 0s or 2s are moved by exchanging elements inside the loop.
  2. Step 2: Implement swap counter

    Introduce a variable initialized to 0 before the loop and increment it each time a swap statement executes.
  3. Final Answer:

    Add a counter and increment it each time a swap occurs inside the loop -> Option D
  4. Quick Check:

    Count swaps during execution [OK]
Hint: Increment counter on every swap inside loop [OK]
Common Mistakes:
  • Counting swaps after sorting by comparing arrays
  • Thinking recursion counts swaps automatically
  • Assuming swaps cannot be tracked
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard