Array partition rearranges elements so that all elements satisfying a predicate come before those that do not. The operation runs in-place and does not require additional storage.
You use it as a primitive in selection, quicksort, filtering, and grouping tasks.
Problem
Given an array of length and a predicate , reorder the array so that:
- for all indices , holds
- for all indices , does not hold
for some partition index .
Algorithm
Use a single pass with a boundary pointer.
partition(A, P):
k = 0
for i from 0 to length(A) - 1:
if P(A[i]):
swap A[i], A[k]
k += 1
return kExample
Let
Partition by even numbers:
| step | i | action | array | k |
|---|---|---|---|---|
| 1 | 0 | 8 even, swap with A[0] | [8, 3, 5, 1, 9] | 1 |
| 2 | 1 | 3 odd | [8, 3, 5, 1, 9] | 1 |
| 3 | 2 | 5 odd | [8, 3, 5, 1, 9] | 1 |
| 4 | 3 | 1 odd | [8, 3, 5, 1, 9] | 1 |
| 5 | 4 | 9 odd | [8, 3, 5, 1, 9] | 1 |
Result:
Partition index:
Correctness
At each step:
- indices contain elements that satisfy
- indices contain elements that do not satisfy
When holds, swapping it into position extends the valid prefix. The invariant is preserved after each iteration. At the end, all elements before satisfy the predicate, and all others follow.
Complexity
| operation | time |
|---|---|
| partition |
Space usage:
When to Use
Array partition is appropriate when:
- elements must be grouped by a condition
- in-place rearrangement is required
- order inside groups does not matter
- used as a step in quicksort or selection
It is less suitable when:
- stability is required
- original order must be preserved
Implementation
def partition(a, predicate):
k = 0
for i in range(len(a)):
if predicate(a[i]):
a[i], a[k] = a[k], a[i]
k += 1
return kfunc Partition[T any](a []T, pred func(T) bool) int {
k := 0
for i := 0; i < len(a); i++ {
if pred(a[i]) {
a[i], a[k] = a[k], a[i]
k++
}
}
return k
}