Sort an array of 0s, 1s and 2s | Dutch National Flag problem

The Dutch National Flag issue adds a twist that is both fascinating and useful to the seemingly straightforward task of sorting arrays. Imagine an array with just 0s, 1s, and 2s, similar to the red, white, and blue of the Dutch flag. This strange work asks us to arrange these elements such that all the 0s congregate to the left, all the 1s to the centre, and all the 2s to the right. We can do this in the realm of Python programming by using a sophisticated method called the Dutch National Flag algorithm. This post will explain the complexities of this issue and walk you through a Python solution that strikes a compromise between clarity and effectiveness. So, let's embark on a journey to master the art of sorting the Dutch way!

The Dutch National Flag Problem

Although sorting an array of 0s, 1s, and 2s might appear simple, it can be rather challenging. In honour of the vibrant stripes of the Dutch flag, we refer to this puzzle as the "Dutch National Flag problem". Think about the colours red, white, and blue. Our objective? efficiently place the 0s, 1s, and 2s in that sequence in an array. In essence, we want all the 0s to be at the front, then the 1s, and finally the 2s. Consider it as planning a colour parade within our Python array!

Problem

Consider the following array: [0, 1, 2, 1, 0, 2, 1]. It is your job to change this array to appear like [0, 0, 1, 1, 1, 2, 2]. Recognise the trend? We're grouping colours to resemble the stripes of the Dutch flag: all the 0s together, then the 1s, then the 2s. Despite its apparent simplicity, the issue is complex and has a clever Python solution.

Two Pointer Algorithm to solve Dutch National Flag Problem

Imagine that you have an array with the three numbers 0, 1, and 2. The objective is to order this array so that all of the 0s appear first, followed by all of the 1s, and then all of the 2s.

We employ an advanced method that does this by keeping track of three-pointers:

  • Low Pointer (low): This Pointer maintains track of the location in the array where the following 0 should go.
  • Middle Pointer (mid): The middle pointer aids in navigating between the items of an array. Each element is examined to see whether it is a 0, 1, or 2.
  • High Pointer (high): The high Pointer designates where in the array the next two should be placed.

Here's how the algorithm works step by step:

  • Initialise the low Pointer to the beginning of the array (index 0), the mid Pointer to the beginning as well, and the high Pointer to the end of the array (index len(arr) - 1).
  • Start a loop that continues until the mid Pointer is less than or equal to the high Pointer.
  • Inside the loop, examine the element at the position pointed to by the mid Pointer:
  • If it's a 0, swap it with the element at the position pointed to by the low Pointer. This effectively moves the 0 to the beginning of the array and increments both low and mid-pointers.
  • If it's a 1, move the mid-Pointer forward one position, as 1s belong in the middle of the sorted array.
  • If it's a 2, swap it with the element at the position pointed to by the high Pointer. This puts the 2 at the end of the array and decrements the high Pointer.

Continue going through these steps until the mid Pointer is no longer less than or equal to the high Pointer.

This function returns a sorted array with all 0s at the beginning, all 1s next, and finally, all 2s at the end. The approach efficiently rearranges the elements with a temporal complexity of O(n), where n is the length of the array.

As a result, the Dutch National Flag algorithm, which was inspired by the colours of the Dutch National Flag, choreographs the sorting of an array of 0s, 1s, and 2s like a perfectly organised parade.

Example Array: [0, 1, 2, 1, 0, 2, 1]

  1. Initialize Pointers: We start with three-pointers: low, mid, and high. Low points to the beginning of the array (index 0), mid also starts at the beginning, and high points to the end of the array (index 6).
    • Array: [0, 1, 2, 1, 0, 2, 1]
    • low: 0, mid: 0, high: 6
  2. Begin Loop: We enter a loop that continues until the mid is less than or equal to high.
  3. Check value at mid: We examine the value at the position pointed by mid, which is 0 in this case.
  4. Value is 0: Since the value is 0, we swap the element at low and mid positions to move the 0 to the beginning.
    • Array after the swap: [0, 1, 2, 1, 0, 2, 1]
    • low: 1, mid: 1, high: 6
  5. Increment low and mid: After the swap, we increment both low and mid-pointers.
    • Array: [0, 0, 2, 1, 1, 2, 1]
    • low: 1, mid: 2, high: 6
  6. Continue Loop: We continue the loop because mid is still less than high.
  7. Check value at mid: We check the value at mid, which is now 2.
  8. Value is 2: Since the value is 2, we swap the element at mid and high positions to move the 2 to the end.
    • Array after the swap: [0, 0, 1, 1, 1, 2, 2]
    • low: 1, mid: 2, high: 5
  9. Decrement high: After the swap, we decrement the high
    • Array: [0, 0, 1, 1, 1, 2, 2]
    • low: 1, mid: 2, high: 4
  10. Continue Loop: We continue the loop again.
  11. Check value at mid: The value at mid is now 1.
  12. Value is 1: Since the value is 1, we increment mid to keep the 1 in the middle.
    • Array: [0, 0, 1, 1, 1, 2, 2]
    • low: 1, mid: 3, high: 4
  13. Continue Loop: We continue the loop.
  14. Check value at mid: The value at mid is still 1.
  15. Value is 1: We increment mid
    • Array: [0, 0, 1, 1, 1, 2, 2]
    • low: 1, mid: 4, high: 4
  16. End Loop: Now, mid is equal to high, so we exit the loop.
  17. Result: The array is now sorted as desired: [0, 0, 1, 1, 1, 2, 2].

And there you have it! The Dutch National Flag algorithm has efficiently sorted the array, just like arranging colours in the Dutch flag - 0s, 1s, and 2s in perfect order.

Approach 1: Two Pointer Approach

Output:

0 0 0 0 0 1 1 1 1 1 2 2

Explanation

  1. Function Definitions:
    • The program begins by defining two functions:
      • sort_array_012(arr, size): This function takes an array arr and its size size as input and sorts it in a specific way.
      • print_sorted_array(arr): This function prints the sorted array arr.
  2. Initialisation:
    • Inside the sort_array_012 function, three variables are initialised: low, high, and mid. These variables are used to keep track of positions in the array while sorting.
    • low is set to 0, high is set to size - 1, and mid is set to 0.
  3. Sorting Loop:
    • A while loop is used to iterate through the array until mid is less than or equal to high.
  4. Sorting Logic:
    • Within the loop, the program checks the value of the element at the mid position:
      • If the element is 0, it swaps the elements at positions low and mid, effectively moving the 0 to the beginning of the array. Then, it increments both low and mid.
      • If the element is 1, it simply increments mid to move to the next element.
      • If the element is 2, it swaps the elements at positions mid and high, moving the 2 to the end of the array. Then, it decrements high.
  5. Return Sorted Array:
    • The sort_array_012 function returns the sorted array arr after the loop is completed.
  6. Printing the Sorted Array:
    • In the print_sorted_array function, a for loop is used to iterate through the sorted array and print each element with a space.
  7. Driver Code:
    • Finally, the driver code outside the functions defines an input array input_array containing 0s, 1s, and 2s.
    • The size of the array is determined using len(input_array).
    • The sort_array_012 function is called to sort the input array, and the sorted result is stored in sorted_array.
    • The print_sorted_array function is called to print the sorted array to the console.
  8. Output:
    • When you run the program, it sorts the input array in a single pass and prints the sorted array as per the Dutch National Flag problem.

Approach 2: The Counting Approach

Approach Explanation:

  1. Counting Frequencies:
    • In this approach, the program first counts the frequencies of 0s, 1s, and 2s in the input array.
    • Three variables cnt0, cnt1, and cnt2 are used to keep track of the counts of 0s, 1s, and 2s, respectively.
  2. Counting Loop:
    • The program iterates through the entire input array.
    • For each element encountered, it checks its value and increments the corresponding count variable.
  3. Updating the Array:
    • After counting the frequencies, the program updates the input array.
    • It starts by filling the array with 0s based on the count of 0s (cnt0).
    • Then, it fills the array with 1s based on the count of 1s (cnt1).
    • Finally, it fills the remaining part of the array with 2s based on the count of 2s (cnt2).
  4. Printing Sorted Array:
    • The program includes a utility function printArr to print the contents of an array.
    • After updating the array, it calls printArr to print the sorted array.
  5. Driver Code:
    • The driver code initialises an input array arr and its length n.
    • It then calls the sortArr function to sort the array according to the Dutch National Flag problem using the counting approach.

Output:

0 0 0 0 0 1 1 1 1 1 2 2

Explanation

  1. Printing Utility Function:
    • The program starts by defining a utility function called printArr. This function is responsible for printing the contents of an array. It takes two parameters: arr (the array to be printed) and n (the length of the array).
  2. Sorting Function:
    • The core sorting logic is implemented in the sortArr function, which is later renamed to dutch_flag_sort_counting in the modified code.
  3. Counting Variables:
    • Inside the sorting function, three variables count_0, count_1, and count_2 are initialised to keep track of the counts of 0s, 1s, and 2s in the input array, respectively.
  4. Counting Loop:
    • The program enters a loop that iterates through the entire input array.
    • For each element encountered, it checks its value and increments the corresponding count variable (count_0, count_1, or count_2) based on whether the element is 0, 1, or 2.
  5. Updating the Array:
    • After counting the frequencies of 0s, 1s, and 2s, the program proceeds to update the input array to sort it.
    • It starts by filling the array with 0s based on the count of 0s (count_0). It does this by repeatedly setting elements to 0 from the beginning of the array while decrementing count_0 and advancing the index i.
    • Similarly, it fills the array with 1s based on the count of 1s (count_1).
    • Finally, it fills the remaining part of the array with 2s based on the count of 2s (count_2).
  6. Printing Sorted Array:
    • After updating the array, the program calls the print_sorted_array function to print the sorted array to the console. This function iterates through the array and prints each element with a space between them.
  7. Driver Code:
    • The driver code at the bottom of the program initialises an input array input_array containing 0s, 1s, and 2s.
    • It calculates the length of the array using len(input_array) to determine the array size.
    • Finally, it calls the dutch_flag_sort_counting function to sort the input array according to the Dutch National Flag problem using the counting approach.





Latest Courses