wavelet_matrix
A Wavelet Matrix for fast queries on a static sequence of integers.
Wavelet Matrix decomposes values into bit layers and supports queries such as:
- access(i): read value at position i
- rank(v, end): count v in a prefix
- select(v, kth): find position of k-th v
- quantile(l, r, kth): k-th smallest in a range
- rich range queries: topk, range_sum, range_freq, range_list, ...
This class automatically chooses an internal representation based on input values.
Construction
Time / Space Complexity
- Time:
O(N log V) - Space:
O(N log V)
where:
N= length of the sequenceV= value domain / range (roughly related to max bit-width)
from wavelet_matrix import WaveletMatrix
wm = WaveletMatrix([5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0])
Return the entire sequence as a Python list.
Complexity
- Time:
O(N log V) - Space:
O(N)
Examples
wm.values()
# [5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0]
Return data[index].
Complexity
- Time:
O(log V) - Space:
O(1)
Examples
wm.access(3)
# 5
Count occurrences of value in the prefix range [0, end).
Complexity
- Time:
O(log V) - Space:
O(1)
Examples
wm.rank(5, 9)
# 4
Return the index of the kth occurrence of value (1-indexed).
Returns None if it does not exist.
Complexity
- Time:
O(log V)(amortized) - Space:
O(1)
Examples
wm.select(5, 4)
# 6
Return the k-th smallest value in [start, end) (1-indexed).
Complexity
- Time:
O(log V) - Space:
O(1)
Examples
wm.quantile(2, 12, 8)
# 5
Return the most frequent values in [start, end).
Result items look like {"value": x, "count": c}.
Complexity
- Time:
O(L (log L) (log V)) - Space:
O(L) - L = number of distinct values in the range
Examples
wm.topk(1, 10, 2)
# [{'value': 5, 'count': 3}, {'value': 1, 'count': 2}]
Sum of values in [start, end).
Complexity
- Time:
O(L log V) - Space:
O(L)
Examples
wm.range_sum(2, 8)
# 24
Intersection of values between two ranges.
Each item: {"value": x, "count1": a, "count2": b}.
Complexity
- Time:
O(L log V) - Space:
O(L)
Examples
wm.range_intersection(0, 6, 6, 11)
# [{'value': 1, 'count1': 1, 'count2': 1}, {'value': 5, 'count1': 3, 'count2': 2}]
Count elements c in [start, end) such that lower <= c < upper.
Complexity
- Time:
O(log V) - Space:
O(1)
Examples
wm.range_freq(1, 9, 4, 6)
# 4
List distinct values c in [start, end) satisfying lower <= c < upper, with counts.
Complexity
- Time:
O(L log V) - Space:
O(L)
Examples
wm.range_list(1, 9, 4, 6)
# [{'value': 4, 'count': 1}, {'value': 5, 'count': 3}]
Return the k largest values in [start, end) with counts.
Complexity
- Time:
O(k log V) - Space:
O(k)
Examples
wm.range_maxk(1, 9, 2)
# [{'value': 6, 'count': 1}, {'value': 5, 'count': 3}]
Return the k smallest values in [start, end) with counts.
Complexity
- Time:
O(k log V) - Space:
O(k)
Examples
wm.range_mink(1, 9, 2)
# [{'value': 1, 'count': 2}, {'value': 2, 'count': 1}]
Return the maximum value c in [start, end) such that c < upper.
Returns None if no value matches.
Complexity
- Time:
O(log V) - Space:
O(1)
Examples
wm.prev_value(1, 9, 7)
# 6
A dynamic wavelet matrix supporting insert/remove/update.
Use this when you need to mutate the sequence.
⚠️ Values must fit within max_bit (bit-width constraint).
Construction
Time / Space Complexity
- Time:
O(N log V) - Space:
O(N log V)
from wavelet_matrix import DynamicWaveletMatrix
dwm = DynamicWaveletMatrix([5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0], max_bit=4)
Return the entire sequence as a Python list.
Complexity
- Time:
O(N log V) - Space:
O(N)
Examples
dwm.values()
# [5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0]
Return data[index].
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.access(3)
# 5
Count occurrences of value in the prefix range [0, end).
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.rank(5, 9)
# 4
Return the index of the kth occurrence of value (1-indexed).
Returns None if it does not exist.
Complexity
- Time:
O((log N) (log V))(amortized) - Space:
O(1)
Examples
dwm.select(5, 4)
# 6
Return the k-th smallest value in [start, end) (1-indexed).
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.quantile(2, 12, 8)
# 5
Return the most frequent values in [start, end).
Result items look like {"value": x, "count": c}.
Complexity
- Time:
O(L (log L) (log N) (log V)) - Space:
O(L) - L = number of distinct values in the range
Examples
dwm.topk(1, 10, 2)
# [{'value': 5, 'count': 3}, {'value': 1, 'count': 2}]
Sum of values in [start, end).
Complexity
- Time:
O(L (log N) (log V)) - Space:
O(L)
Examples
dwm.range_sum(2, 8)
# 24
Intersection of values between two ranges.
Each item: {"value": x, "count1": a, "count2": b}.
Complexity
- Time:
O(L (log N) (log V)) - Space:
O(L)
Examples
dwm.range_intersection(0, 6, 6, 11)
# [{'value': 1, 'count1': 1, 'count2': 1}, {'value': 5, 'count1': 3, 'count2': 2}]
Count elements c in [start, end) such that lower <= c < upper.
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.range_freq(1, 9, 4, 6)
# 4
List distinct values c in [start, end) satisfying lower <= c < upper, with counts.
Complexity
- Time:
O(L (log N) (log V)) - Space:
O(L)
Examples
dwm.range_list(1, 9, 4, 6)
# [{'value': 4, 'count': 1}, {'value': 5, 'count': 3}]
Return the k largest values in [start, end) with counts.
Complexity
- Time:
O(k (log N) (log V)) - Space:
O(k)
Examples
dwm.range_maxk(1, 9, 2)
# [{'value': 6, 'count': 1}, {'value': 5, 'count': 3}]
Return the k smallest values in [start, end) with counts.
Complexity
- Time:
O(k (log N) (log V)) - Space:
O(k)
Examples
dwm.range_mink(1, 9, 2)
# [{'value': 1, 'count': 2}, {'value': 2, 'count': 1}]
Return the maximum value c in [start, end) such that c < upper.
Returns None if no value matches.
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.prev_value(1, 9, 7)
# 6
Return the minimum value c in [start, end) such that lower <= c.
Returns None if no value matches.
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.next_value(1, 9, 3)
4
Return the maximum bit-length allowed for stored values.
Complexity
- Time:
O(1) - Space:
O(1)
Examples
dwm.max_bit()
# 4
Insert value at index.
⚠️ value must fit within max_bit.
Complexity
- Time:
O((log N) (log V)) - Space:
O(1)
Examples
dwm.insert(3, 10)