-
Notifications
You must be signed in to change notification settings - Fork 3
/
maxmin.py
52 lines (48 loc) · 1.46 KB
/
maxmin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
"""
by travisbrady
A Python implementation of Daniel Lemire's Streaming Maximum-Minimum Filter
'Streaming Maximum-Minimum Filter Using No More than Three Comparisons per Element'
http://arxiv.org/abs/cs.DS/0610046
"""
from collections import deque
def supermaxmin(a, w):
"""
# a: array to compute filter over
# w: window width
>>> a = [9, 0, 5, 1, 11, 23, 55, 4, 16, 47, 33]
>>> w = 3
>>> supermaxmin(a, w)
([9, 5, 11, 23, 55, 55, 55, 47, 47], [0, 0, 1, 1, 11, 4, 4, 4, 16])
"""
maxfifo, minfifo = deque((0,)), deque((0,))
lena = len(a)
maxvalues = [None]*(lena-w+1)
minvalues = [None]*(lena-w+1)
for i in xrange(1, lena):
if i >= w:
maxvalues[i-w] = a[maxfifo[0]]
minvalues[i-w] = a[minfifo[0]]
if a[i] > a[i-1]:
maxfifo.pop()
while maxfifo:
if a[i] <= a[maxfifo[-1]]:
break
maxfifo.pop()
else:
minfifo.pop()
while minfifo:
if a[i] >= a[minfifo[-1]]:
break
minfifo.pop()
maxfifo.append(i)
minfifo.append(i)
if i == (w+maxfifo[0]):
maxfifo.popleft()
elif i == (w + minfifo[0]):
minfifo.popleft()
maxvalues[lena-w] = a[maxfifo[0]]
minvalues[lena-w] = a[minfifo[0]]
return maxvalues, minvalues
if __name__ == '__main__':
import doctest
doctest.testmod()