Possible Duplicate:
Find the min number in all contiguous subarrays of size l of a array of size n
I have a (large) array of numeric data (size N
) and would like to compute an array of running maximums with a fixed window size w
.
More directly, I can define a new array out[k-w+1] = max{data[k-w+1,...,k]}
for k >= w-1
(this assumes 0-based arrays, as in C++).
Is there a better way to do this than N log(w)
?
[I'm hoping there should be a linear one in N
without dependence on w
, like for moving average, but cannot find it. For N log(w)
I think there is a way to manage with a sorted data structure which will do insert()
, delete()
and extract_max()
altogether in log(w)
or less on a structure of size w
-- like a sorted binary tree, for example].
Thank you very much.
I'll demonstrate how to do it with the list:
L = [21, 17, 16, 7, 3, 9, 11, 18, 19, 5, 10, 23, 20, 15, 4, 14, 1, 2, 22, 13, 8, 12, 6]
with length N=23
and W = 4
.
Make two new copies of your list:
L1 = [21, 17, 16, 7, 3, 9, 11, 18, 19, 5, 10, 23, 20, 15, 4, 14, 1, 2, 22, 13, 8, 12, 6]
L2 = [21, 17, 16, 7, 3, 9, 11, 18, 19, 5, 10, 23, 20, 15, 4, 14, 1, 2, 22, 13, 8, 12, 6]
Loop from i=0
to N-1
. If i
is not divisible by W
, then replace L1[i]
with max(L1[i],L1[i-1])
.
L1 = [21, 21, 21, 21, | 3, 9, 11, 18, | 19, 19, 19, 23 | 20, 20, 20, 20 | 1, 2, 22, 22 | 8, 12, 12]
Loop from i=N-2
to0
. If i+1
is not divisible by W
, then replace L2[i]
with max(L2[i], L2[i+1])
.
L2 = [21, 17, 16, 7 | 18, 18, 18, 18 | 23, 23, 23, 23 | 20, 15, 14, 14 | 22, 22, 22, 13 | 12, 12, 6]
Make a list L3
of length N + 1 - W
, so that L3[i] = max(L2[i]
, L1[i + W - 1])
L3 = [21, 17, 16, 11 | 18, 19, 19, 19 | 23, 23, 23, 23 | 20, 15, 14, 22 | 22, 22, 22, 13]
Then this list L3
is the moving maxima you seek, L2[i]
is the maximum of the range between i
and the next vertical line, while l1[i + W - 1]
is the maximum of the range between the vertical line and i + W - 1
.
There is indeed an algorithm that can do this in O(N) time with no dependence on the window size w. The idea is to use a clever data structure that supports the following operations:
This is essentially a queue data structure that supports access (but not removal) of the maximum element. Amazingly, as seen in this earlier question, it is possible to implement this data structure such that each of these operations runs in amortized O(1) time. As a result, if you use this structure to enqueue w elements, then continuously dequeue and enqueue another element into the structure while calling find-max as needed, it will take only O(n + Q) time, where Q is the number of queries you make. If you only care about the minimum of each window once, this ends up being O(n), with no dependence on the window size.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With