The Dutch National Flag Problem (The Quicksort "Band-Aid")

Back To Back SWE · Beginner ·🏗️ Systems Design & Architecture ·7y ago

Key Takeaways

The Dutch National Flag Problem is solved using three approaches: building three arrays, using a two-pointer technique, and using a linear scan approach, with a focus on partitioning schemes and array manipulation.

Full Transcript

I kid you not when I say we are in a literal basement no like for real we are actually in a basement I kid you not we are in a basement this might be our whiteboard today we have our exquisite markers the top-of-the-line Ahri marks markers nope we upgraded look at these whiteboards ah so many whiteboards alright so today we have a very interesting problem called the Dutch national flag problem this is also a notable problem in computer science this problem is very similar to the quicksort partitioning scheme that we see in the quicksort algorithm you'll see why shortly so what is the Dutch national flag problem asking us given an array and a pivot index in that array rearrange the elements of the array so that they fall into three categories and they might not always follow to these three categories well they always fall into these three categories but one of the categories might not exist cut the array into an array of elements all before the pivot elements all equal to the pivot and elements all greater than the pivot not that they the index but the value sitting at the pivot index so let's go through examples so we can clearly see what's going on here so I color-coded it green is items less brown is items equal to and read his items greater than the value of the pivot index here is an example here's our example array that indexes are numbered above where you can just count them out yourself if we choose three as the pivot index what value is at nx30 when you need to repartition this array around the value 0 so every value less than 0 needs to be to the left of it every value equal to 0 needs to be grouped together and every value greater than 0 needs to be passed all of the zeros so as you can see here we have all our zeros here ok we have a brown region great and then all the ones you choose are to view to the right to the right of 0 so this creates a kind of coloring like the Dutch national flag duster national flag has three colors so that's kind of where the problems name comes from and in this case we will be missing one of the colors of the flag if our pivot element is the greatest item in the array or it is the least item in the right this is this means that our pivot element is going to be at the edges of the array pushing out one of the colors of the flag so this zero is on the left of the array all items greater than it must be to the right of it so we're only gonna have one color and then the rest so here let's do another example so let's pick pivot index 2 so pivot index 2 we have the value of 2 at pivot index 2 so we have a value of 2 so we need to repartition our array so all numbers less than 2 appear to the left of 2 all numbers equal to 2 stay in the one section and all of the numbers that are greater than 2 are to the right of that middle section here are two valid partitioning schemes that our program could output so for this we see all the zeros and ones are to the left of 2 because they're less than 2 and then we have all our twos in one part and then here we have all our zeros and once again they're in there in their own region and then we have our twos in their own region so the thing is both of these are valid because we partitioned based on these rules everything less than 2 is to the left of it we're fine this is a valid partitioning so this is more perfect than this because we have a sorted order here how are we going to do this how can we do this so there's basically three approaches to this problem all of them use basic array you know swaps and things so let's get into the three approaches to this problem all right so let's look at the three approaches we have to this problem the straightforward solution build three arrays build three arrays both a array of items less than the pivot built an array of items equal to the pivot those an array of items greater than the pivot so what is this going to say this is going to take all of n space because we have n elements and it's going to take we're gonna have to do one pass to build to the three arrays and then another pass to place all of the elements from the arrays that we built back into a to overwrite a to repartition it so this means we're going to have all events space and all event plus of n time which is just going to be linear time overall so that's what we have here so as you can see we have this is our first way we can do it build three arrays and then replace those back into a what is a better way we could do we can do this in place and keep our space constant we don't want to create space that's going to scale with our input so let's keep space constant for next two ways of doing it so the second way we can do it if we can do this with two passes we can do a forward pass to place the elements less than the pivot and a backwards pass to place elements greater than the pivot and in our backwards pass we keep going until we see an item less than the pivot which means we've we've encroached we've we've overstepped into what we've already placed at the beginning we've reached the first color of the flag which is the the region that's less than the pivot and we can stop turning our backwards backwards iteration so 202 linear time passes which would add up to a linear time a linear time run time but in the in the less efficient approach for each element so when I'm here when I'm start here during the forwards pass for each elements I will look for an element that is less than the pivot and place it here and swap my that myself with that item so if my pivot value was 1 I would look for a value less than 1 which is this value so I just keep advancing when I'm here I would scan the whole array for an item that is less than the pivot value I find zero here swap these this is going to be all of N squared in time because for each element for each of the N elements we're going to be doing an layer time o of n pass so n times n we have N squared although it's going to be a triangular number of sorts it's going to still become around like I don't like half I'm squit 1/2 n square we're just N squared in time what do we do how else could we do this well the problem is why are we going to do a whole pass on the whole array to finally make smallest elements to swap ourselves with when in reality we can just do our forwards or backwards pass for the forwards pass example we can just do our forwards pass and just remember where to place the smallest item so let's walk through what I'm saying right now so it becomes very clear we're going to use a placement indicee to repartition when we're going forward and backwards to keep ourself linear in time let's see what I mean all right so now let's walk through it and let's do our forward pass we'll replace the items less than the pivot here is our original array here's the array we're gonna be messing around with our pivot indexes index 1 and the value at index 1 is 1 so we're going to be pivoting around 1 all items less than 1 will be to the left all items equal to 1 will be in in in their own little section and all items greater than 1 will be greater and off to the right so now we're gonna do our little scan on the array and we're gonna keep a placement index so our placement index is right here so we're gonna place right there we're gonna have our arrow let's make that bigger so this is where we're gonna place in the right so we're gonna see we're gonna start it in X 0 and we're gonna compare items and place them in there if they're less than the pivot is 0 less than 1 yes place it and advance our pivot advance our placement all right now we're looking here is 1 less than 1 no is 2 less than 1 no is 0 less than 1 yes so we just swapped index 1 and index 3 as you can see we swap these guys and replace them in here and now we're placing on index 2 we're placing on index 2 now so now okay we just swapped with this now we need to look is 2 less than 1 no is 1 less than 1 no is 1 less than 1 no we're finished with our forward pass and what can you see here all the items less than the pivot are at the beginning of the array all right and now let's go backwards let's move backwards and place all of the items greater than our pivot index value again we're comparing against pivot index 1 which holds the value of 1 so now we're gonna place our placement here so now is one greater than one know is one greater than one no it's two greater than one yes so we'll swap index for an index six all right so then we just swapped index for an index six and now is one greater than one no it's two greater than one two is greater than one let's do another swap all right so we just swapped index two and index five and now our new placement is at index 4 we're gonna place our neck here our greatest item there and you see how we're remembering where our placement needs to go instead of doing a scan every time that's how we took it from all events square to linear oh of n now so now we're here and we just did we just did a flip here and now we hit zero is zero greater than one well zero is less than the pivot index down zero is less than the pivot of X and now we are encroaching on what we already did we're already stepping into the lesser region this is when our backwards iteration stops we end our backwards iteration and now if you notice our problem is finished we have two we have three sections and now you can see we have our Dutch national flag we have the region less than our pivot value or pivot and x1 value of one we have our region equal to one and we ever read u greater than one so this is the Dutch national flag interview problem this is how you approach it this is how we took it from using a ton of space to doing all of N squared to realize in weight we could just use a placement pointer to remember where our placements go and just do our forwards and backwards scan and place items this is the problem and if you liked this video hit the like button subscribe to the channel if you want more interview questions like this and I'm gonna get out of this basement now [Music]

Original Description

Free 5-Day Mini-Course: https://backtobackswe.com Try Our Full Platform: https://backtobackswe.com/pricing 📹 Intuitive Video Explanations 🏃 Run Code As You Learn 💾 Save Progress ❓New Unseen Questions 🔎 Get All Solutions The relevance of this problem is in its applications to quicksort. If we pick bad pivots for quicksort then we will have a O(n^2) runtime which is very bad. The way of repartitioning an array as shown in O(n) time aids in this issue of repeated elements in an array being sorted. You can read more here: https://en.wikipedia.org/wiki/Dutch_national_flag_problem The code for this problem is pretty straightforward to do (just 2 for loops, one going forward and one going backward UNTIL we hit the region less than the pivot). If you really want to see the code, this problem can be found in the amazing book Elements of Programming Interviews by Adnan Aziz as question 6.1 ++++++++++++++++++++++++++++++++++++++++++++++++++ Question: Write a program that takes an array A and an index i into A, and rearranges the elements such that 1.) All elements less than A[i] (the "pivot") appear first 2.) Followed by elements equal to the pivot 3.) Followed by elements greater than the pivot Example A = [0, 1, 2, 0, 2, 1, 1] (same array) Pivot Index = 2 Valid Output: [0, 1, 0, 1, 1, 2, 2] Valid Output: [0, 0, 1, 1, 1, 2, 2] (a more perfect output) This is called Dutch national flag partitioning because the Dutch national flag consists of three horizontal bands, each in a different color. We will get an input and attempt to form a 3 section partitioning of the array and will always end up with these 3 sections of "lesser", "equal", and "greater" value UNLESS the value at our partition index is the smallest OR greatest value in the array. Approach 2 Rather than create extra space, we can just do 2 passes, one forward, and then one backward. During the forward pass for each element in the array, we will look for an element smaller than the eleme
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from Back To Back SWE · Back To Back SWE · 11 of 60

1 4 Tips To Learn Java Programming As Fast As Possible As A Beginner
4 Tips To Learn Java Programming As Fast As Possible As A Beginner
Back To Back SWE
2 3 Mistakes Beginners Make When First Learning Java and Android Development
3 Mistakes Beginners Make When First Learning Java and Android Development
Back To Back SWE
3 How To Get A Job At Google | The Ultimate Guide To Algorithmic/Coding Interviews
How To Get A Job At Google | The Ultimate Guide To Algorithmic/Coding Interviews
Back To Back SWE
4 The Ultimate Big O Notation Tutorial (Time & Space Complexity For Algorithms)
The Ultimate Big O Notation Tutorial (Time & Space Complexity For Algorithms)
Back To Back SWE
5 Total Occurrences Of K In A Sorted Array (Facebook Software Engineering Interview Question)
Total Occurrences Of K In A Sorted Array (Facebook Software Engineering Interview Question)
Back To Back SWE
6 The N Queens Problem using Backtracking/Recursion - Explained
The N Queens Problem using Backtracking/Recursion - Explained
Back To Back SWE
7 Compute All Mnemonics For A Phone Number (Recursion/Backtracking Problem)
Compute All Mnemonics For A Phone Number (Recursion/Backtracking Problem)
Back To Back SWE
8 How To Reverse A Singly Linked List | The Ultimate Explanation (Iteratively & Recursively)
How To Reverse A Singly Linked List | The Ultimate Explanation (Iteratively & Recursively)
Back To Back SWE
9 Depth First & Breadth First Graph Search - DFS & BFS Graph Searching Algorithms
Depth First & Breadth First Graph Search - DFS & BFS Graph Searching Algorithms
Back To Back SWE
10 The 0/1 Knapsack Problem (Demystifying Dynamic Programming)
The 0/1 Knapsack Problem (Demystifying Dynamic Programming)
Back To Back SWE
The Dutch National Flag Problem (The Quicksort "Band-Aid")
The Dutch National Flag Problem (The Quicksort "Band-Aid")
Back To Back SWE
12 Test If A Binary Tree Is Symmetric ("Symmetric Tree" on Leetcode)
Test If A Binary Tree Is Symmetric ("Symmetric Tree" on Leetcode)
Back To Back SWE
13 The IP Address Decomposition Problem - Compute All Valid IP Addresses From Raw IP String
The IP Address Decomposition Problem - Compute All Valid IP Addresses From Raw IP String
Back To Back SWE
14 How To Permute A String - Generate All Permutations Of A String
How To Permute A String - Generate All Permutations Of A String
Back To Back SWE
15 The Balanced Parentheses Problem - Classic Stack Problem ("Valid Parentheses" on Leetcode)
The Balanced Parentheses Problem - Classic Stack Problem ("Valid Parentheses" on Leetcode)
Back To Back SWE
16 Knuth–Morris–Pratt (KMP) Pattern Matching Substring Search -  First Occurrence Of Substring
Knuth–Morris–Pratt (KMP) Pattern Matching Substring Search - First Occurrence Of Substring
Back To Back SWE
17 Implement An LRU Cache - The LRU Cache Eviction Policy ("LRU Cache" on LeetCode)
Implement An LRU Cache - The LRU Cache Eviction Policy ("LRU Cache" on LeetCode)
Back To Back SWE
18 Find The Longest Increasing Subsequence - Dynamic Programming Fundamentals
Find The Longest Increasing Subsequence - Dynamic Programming Fundamentals
Back To Back SWE
19 Generate All Palindromic Decompositions Of A String ("Palindrome Partitioning" on Leetcode)
Generate All Palindromic Decompositions Of A String ("Palindrome Partitioning" on Leetcode)
Back To Back SWE
20 Implement A Sudoku Solver - Sudoku Solving Backtracking Algorithm ("Sudoku Solver" on LeetCode)
Implement A Sudoku Solver - Sudoku Solving Backtracking Algorithm ("Sudoku Solver" on LeetCode)
Back To Back SWE
21 Merge K Sorted Arrays - Min Heap Algorithm ("Merge K Sorted Lists" on LeetCode)
Merge K Sorted Arrays - Min Heap Algorithm ("Merge K Sorted Lists" on LeetCode)
Back To Back SWE
22 Partition To K Equal Sum Subsets From An Array of Integers - The Backtracking Approach
Partition To K Equal Sum Subsets From An Array of Integers - The Backtracking Approach
Back To Back SWE
23 Edit Distance Between 2 Strings - The Levenshtein Distance ("Edit Distance" on LeetCode)
Edit Distance Between 2 Strings - The Levenshtein Distance ("Edit Distance" on LeetCode)
Back To Back SWE
24 Total Ways To Decode A String - Recursive Dynamic Programming Approach ("Decode Ways" on LeetCode)
Total Ways To Decode A String - Recursive Dynamic Programming Approach ("Decode Ways" on LeetCode)
Back To Back SWE
25 The Change Making Problem - Fewest Coins To Make Change Dynamic Programming
The Change Making Problem - Fewest Coins To Make Change Dynamic Programming
Back To Back SWE
26 Compute The Next Permutation of A Numeric Sequence - Case Analysis ("Next Permutation" on Leetcode)
Compute The Next Permutation of A Numeric Sequence - Case Analysis ("Next Permutation" on Leetcode)
Back To Back SWE
27 Count Total Unique Binary Search Trees - The nth Catalan Number (Dynamic Programming)
Count Total Unique Binary Search Trees - The nth Catalan Number (Dynamic Programming)
Back To Back SWE
28 Generate All Strings With n Matched Parentheses - Backtracking ("Generate Parentheses" on LeetCode)
Generate All Strings With n Matched Parentheses - Backtracking ("Generate Parentheses" on LeetCode)
Back To Back SWE
29 Implement A Max Stack - A Stack With A .max() API (Similar To "Min Stack" on LeetCode)
Implement A Max Stack - A Stack With A .max() API (Similar To "Min Stack" on LeetCode)
Back To Back SWE
30 The Recursive Staircase - Top Down & Bottom Up Dynamic Programming ("Climbing Stairs" on LeetCode)
The Recursive Staircase - Top Down & Bottom Up Dynamic Programming ("Climbing Stairs" on LeetCode)
Back To Back SWE
31 Search A Maze For Any Path - Depth First Search Fundamentals (Similar To "The Maze" on Leetcode)
Search A Maze For Any Path - Depth First Search Fundamentals (Similar To "The Maze" on Leetcode)
Back To Back SWE
32 Total Unique Ways To Make Change - Dynamic Programming ("Coin Change 2" on LeetCode)
Total Unique Ways To Make Change - Dynamic Programming ("Coin Change 2" on LeetCode)
Back To Back SWE
33 Test If A Binary Tree Is Height Balanced ("Balanced Binary Tree" on LeetCode)
Test If A Binary Tree Is Height Balanced ("Balanced Binary Tree" on LeetCode)
Back To Back SWE
34 Find The Second Largest Item - Heap & Tracking Approach (Beginner Big N Interview Question)
Find The Second Largest Item - Heap & Tracking Approach (Beginner Big N Interview Question)
Back To Back SWE
35 Increment An Integer Represented As An Array ("Plus One" on LeetCode)
Increment An Integer Represented As An Array ("Plus One" on LeetCode)
Back To Back SWE
36 Merge 2 Sorted Lists - A Fundamental Merge Sort Subroutine ("Merge Two Sorted Lists" on LeetCode)
Merge 2 Sorted Lists - A Fundamental Merge Sort Subroutine ("Merge Two Sorted Lists" on LeetCode)
Back To Back SWE
37 Clone An Undirected Graph - The Utility of Hashtable Mappings ("Clone Graph" on Leetcode)
Clone An Undirected Graph - The Utility of Hashtable Mappings ("Clone Graph" on Leetcode)
Back To Back SWE
38 Clone A Linked List (With Random Pointers) - Linear Space Solution & Tricky Constant Space Solution
Clone A Linked List (With Random Pointers) - Linear Space Solution & Tricky Constant Space Solution
Back To Back SWE
39 Deeply Understanding Logarithms In Time Complexities & Their Role In Computer Science
Deeply Understanding Logarithms In Time Complexities & Their Role In Computer Science
Back To Back SWE
40 Implement A Binary Heap - An Efficient Implementation of The Priority Queue ADT (Abstract Data Type)
Implement A Binary Heap - An Efficient Implementation of The Priority Queue ADT (Abstract Data Type)
Back To Back SWE
41 Max Contiguous Subarray Sum - Cubic Time To Kadane's Algorithm ("Maximum Subarray" on LeetCode)
Max Contiguous Subarray Sum - Cubic Time To Kadane's Algorithm ("Maximum Subarray" on LeetCode)
Back To Back SWE
42 Binary Tree Bootcamp: Full, Complete, & Perfect Trees. Preorder, Inorder, & Postorder Traversal.
Binary Tree Bootcamp: Full, Complete, & Perfect Trees. Preorder, Inorder, & Postorder Traversal.
Back To Back SWE
43 What Is Asymptotic Analysis? And Why Does It Matter? A Deeper Understanding of Asymptotic Notation.
What Is Asymptotic Analysis? And Why Does It Matter? A Deeper Understanding of Asymptotic Notation.
Back To Back SWE
44 An In-Depth Algorithmic Analysis of Bubble Sort. Best Case, Average Case, & Worst Case.
An In-Depth Algorithmic Analysis of Bubble Sort. Best Case, Average Case, & Worst Case.
Back To Back SWE
45 Maximum Sum Rectangle In A 2D Matrix - Kadane's Algorithm Applications (Dynamic Programming)
Maximum Sum Rectangle In A 2D Matrix - Kadane's Algorithm Applications (Dynamic Programming)
Back To Back SWE
46 A Detailed Algorithmic Analysis of Insertion Sort. Best Case & Worst Case.
A Detailed Algorithmic Analysis of Insertion Sort. Best Case & Worst Case.
Back To Back SWE
47 Binary Tree Level Order Traversal - Drawing The Parallel Between Trees & Graphs
Binary Tree Level Order Traversal - Drawing The Parallel Between Trees & Graphs
Back To Back SWE
48 Implement A Queue Using Stacks - The Queue ADT ("Implement Queue Using Stacks" on LeetCode)
Implement A Queue Using Stacks - The Queue ADT ("Implement Queue Using Stacks" on LeetCode)
Back To Back SWE
49 All Nodes Distance K In A Binary Tree - Performing Bidirectional Search On A Tree Using A Hashtable
All Nodes Distance K In A Binary Tree - Performing Bidirectional Search On A Tree Using A Hashtable
Back To Back SWE
50 Longest Common Subsequence (2 Strings) - Dynamic Programming & Competing Subproblems
Longest Common Subsequence (2 Strings) - Dynamic Programming & Competing Subproblems
Back To Back SWE
51 Egg Dropping Problem: Dynamic Programming Fundamentals & Understanding Subproblem Decomposition
Egg Dropping Problem: Dynamic Programming Fundamentals & Understanding Subproblem Decomposition
Back To Back SWE
52 Minimum Window Substring: Utilizing Two Pointers & Tracking Character Mappings With A Hashtable
Minimum Window Substring: Utilizing Two Pointers & Tracking Character Mappings With A Hashtable
Back To Back SWE
53 Reverse Polish Notation: Types of Mathematical Notations & Using A Stack To Solve RPN Expressions
Reverse Polish Notation: Types of Mathematical Notations & Using A Stack To Solve RPN Expressions
Back To Back SWE
54 Asymptotic Notations 101: Big O, Big Omega, & Theta (Asymptotic Analysis Bootcamp)
Asymptotic Notations 101: Big O, Big Omega, & Theta (Asymptotic Analysis Bootcamp)
Back To Back SWE
55 The Backtracking Blueprint: The Legendary 3 Keys To Backtracking Algorithms
The Backtracking Blueprint: The Legendary 3 Keys To Backtracking Algorithms
Back To Back SWE
56 Fast Multiplication: From Grade-School Multiplication To Karatsuba's Algorithm
Fast Multiplication: From Grade-School Multiplication To Karatsuba's Algorithm
Back To Back SWE
57 Search A 2D Sorted Matrix - Fundamentals of Search Space Reduction
Search A 2D Sorted Matrix - Fundamentals of Search Space Reduction
Back To Back SWE
58 The Quicksort Sorting Algorithm: Pick A Pivot, Partition, & Recurse
The Quicksort Sorting Algorithm: Pick A Pivot, Partition, & Recurse
Back To Back SWE
59 Lowest Common Ancestor Between 2 Binary Tree Nodes (A Recursive Approach)
Lowest Common Ancestor Between 2 Binary Tree Nodes (A Recursive Approach)
Back To Back SWE
60 Sort A K Sorted Array - Investigating Applications of Min/Max Heaps
Sort A K Sorted Array - Investigating Applications of Min/Max Heaps
Back To Back SWE

The Dutch National Flag Problem is a classic problem in computer science that involves rearranging an array into three categories. This video explains three approaches to solving the problem and provides a detailed analysis of the time and space complexity of each approach.

Key Takeaways
  1. Build three arrays to solve the Dutch National Flag problem
  2. Use a two-pointer technique to swap elements as necessary
  3. Use a linear scan approach to make a single pass through the array
  4. Do a forward pass to place elements less than the pivot
  5. Do a backward pass to place elements greater than the pivot
  6. Use a placement index to repartition array in linear time
  7. Advance the pivot
  8. Compare items and place them in the correct region
  9. Swap items in the array
  10. Move backwards and place items greater than the pivot in the correct region
💡 The Dutch National Flag Problem can be solved in O(n) time using a two-pass approach with forward and backward passes, reducing space usage from O(n) to O(1).

Related Reads

📰
Designing for the Surge: The Real-World Cost of Separating Reads and Writes
Learn how separating reads and writes can impact system performance and cost in real-world scenarios, particularly in high-traffic applications
Dev.to · shubham shaw
📰
Building NovaOS: A 16-bit Operating System from Scratch (in Assembly and C)
Learn to build a 16-bit operating system from scratch using Assembly and C, a fundamental project for low-level programming enthusiasts
Dev.to · Daniel Developer
📰
Stop Writing 40-Method Repositories: The Specification Pattern in Symfony
Learn to avoid fat repositories in Symfony by applying the Specification Pattern to improve code organization and maintainability
Medium · Programming
📰
You Don’t Have a Performance Problem — You Have a Design Problem
Most performance issues stem from design flaws, not coding errors, and can be solved by reevaluating system architecture
Medium · Programming
Up next
API vs MCP Explained in Telugu | What’s the Difference? | Complete Beginner Guide
Withmesravani_
Watch →