Partition an array while preserving the relative order of elements inside each group.
Stable partition rearranges an array so that elements satisfying a predicate appear before the others, while preserving relative order inside both groups.
You use it when grouping is required but original order still carries meaning.
Problem
Given an array of length and a predicate , reorder the array so that:
- all elements satisfying appear first
- all elements not satisfying appear after them
- relative order inside each group is preserved
Algorithm
Use two temporary arrays. Store matching elements in one array and non-matching elements in another, then concatenate them.
stable_partition(A, P):
yes = empty array
no = empty array
for x in A:
if P(x):
append x to yes
else:
append x to no
k = 0
for x in yes:
A[k] = x
k += 1
for x in no:
A[k] = x
k += 1
return length(yes)Example
Let
Partition by even numbers:
| pass | element | group |
|---|---|---|
| 1 | 8 | yes |
| 2 | 3 | no |
| 3 | 5 | no |
| 4 | 2 | yes |
| 5 | 1 | no |
| 6 | 4 | yes |
The stable groups are:
and
Final array:
Return partition index .
Correctness
The algorithm scans elements from left to right. Each element that satisfies is appended to yes in its original order. Each remaining element is appended to no in its original order.
Writing all elements from yes before all elements from no produces a valid partition, and each group keeps the same relative order as in the input.
Complexity
| operation | time |
|---|---|
| scan input | |
| write output | |
| total |
Space usage:
An in-place stable partition is possible, but it is more complex and often slower in practice.
When to Use
Stable partition is appropriate when:
- elements must be grouped by a predicate
- relative order matters
- extra memory is acceptable
- predictable linear behavior is preferred
It is less suitable when memory must remain constant and stability is not required.
Implementation
def stable_partition(a, predicate):
yes = []
no = []
for x in a:
if predicate(x):
yes.append(x)
else:
no.append(x)
k = 0
for x in yes:
a[k] = x
k += 1
for x in no:
a[k] = x
k += 1
return len(yes)func StablePartition[T any](a []T, pred func(T) bool) int {
yes := make([]T, 0)
no := make([]T, 0)
for _, x := range a {
if pred(x) {
yes = append(yes, x)
} else {
no = append(no, x)
}
}
k := 0
for _, x := range yes {
a[k] = x
k++
}
for _, x := range no {
a[k] = x
k++
}
return len(yes)
}