How do you find the maximum value in every window of a given size?
Use a deque that holds the indices of the candidates for the maximum, with their values in decreasing order. When a new value arrives you remove from the back every index whose value is smaller, because the new value makes them redundant. You also drop from the front any index that has fallen out of the window, and the front of the deque always points at the current maximum.
from collections import deque
def window_max(values, k):
window = deque()
result = []
for i, value in enumerate(values):
while window and values[window[-1]] <= value:
window.pop()
window.append(i)
if window[0] <= i - k:
window.popleft()
if i >= k - 1:
result.append(values[window[0]])
return result
print(window_max([1, 3, -1, -3, 5, 3, 6, 7], 3))
print(window_max([1], 1))The outputs are 3, 3, 5, 5, 6, 7 and 1. The windows of size three have maxima of three, three, five, five, six and seven.
The mechanism is the redundancy rule. If a new value is at least as large as an element behind it, that element can never be the maximum of a window containing both, because the new value will leave the window later and is at least as big. So removing it loses nothing. The deque therefore holds only elements that could still become the maximum, and the front is always the answer.
The trade-off to name is that the answer has to be the front of the deque, so you need a structure that supports removal from both ends, which is exactly what a deque provides and what a plain list does not. The complexity is linear because every index is added once and removed at most once, from either end, so the amortised cost per element is constant even though a single iteration may do several removals.