This is a single-pass, in-place partitioning of an array into three groups, like the Dutch flag has three horizontal bands of colors (red, white, blue). It’s a special case of multi-way partitioning, and forms the basis of efficient three-way Quick Sort and other algorithms where you need to group items by one of three categories.
Problem
You have an array A[0…n−1]
whose elements each belong to one of three categories (often represented as 0, 1, 2 or ‘R’, ‘W’, ‘B’). Rearrange the array in-place so that all 0s come first, then all 1s, then all 2s. You may only swap elements; you want a single linear-time pass.
Solution
- Maintain three regions in the array:
[0 … low−1]
= “all 0s”[low … mid−1]
= “all 1s”[mid … high]
= “unknown”[high+1 … n−1]
= “all 2s”
- initialize
low = 0, mid = 0, high = n−1
- Loop while
mid ≤ high
and inspectA[mid]
:if (A[mid] == 0)
swap(A[low], A[mid]);
low++; mid++;
else if A[mid] == 1
mid++;
else (A[mid] == 2)
swap(A[mid], A[high]);
high––;
- do not increment mid here, since the swapped-in element at mid is unexamined
Before each iteration
- Everything left of
low
is 0 - Between
low
andmid−1
is 1 - Between
mid
andhigh
is unknown - Right of
high
is 2
Because each swap either grows the 0-region or the 2-region (or skips over a 1), and mid
only moves forward, the loop terminates in O(n) time.
- Time: O(n) — each element is examined at most once; swaps are O(1).
- Space: O(1) — in-place, only three extra indices.
#include <vector>
#include <algorithm>
using namespace std;
// 0,1,2 partition in one pass: Dutch National Flag
void dutchFlagPartition(vector<int>& A) {
int low = 0, mid = 0, high = (int)A.size() - 1;
while (mid <= high) {
if (A[mid] == 0) {
swap(A[low], A[mid]);
++low; ++mid;
}
else if (A[mid] == 1) {
++mid;
}
else { // A[mid] == 2
swap(A[mid], A[high]);
--high;
}
}
}