Skip to content

Commit ca5b8c1

Browse files
Add sliding window maximum using monotonic deque (#14133)
* feat: add sliding window maximum using monotonic deque * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * feat: add sliding window maximum using monotonic deque --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 3c88735 commit ca5b8c1

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

other/sliding_window_maximum.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from collections import deque
2+
3+
4+
def sliding_window_maximum(numbers: list[int], window_size: int) -> list[int]:
5+
"""
6+
Return a list containing the maximum of each sliding window of size window_size.
7+
8+
This implementation uses a monotonic deque to achieve O(n) time complexity.
9+
10+
Args:
11+
numbers: List of integers representing the input array.
12+
window_size: Size of the sliding window (must be positive).
13+
14+
Returns:
15+
List of maximum values for each valid window.
16+
17+
Raises:
18+
ValueError: If window_size is not a positive integer.
19+
20+
Time Complexity: O(n) - each element is added and removed at most once
21+
Space Complexity: O(k) - deque stores at most window_size indices
22+
23+
Examples:
24+
>>> sliding_window_maximum([1, 3, -1, -3, 5, 3, 6, 7], 3)
25+
[3, 3, 5, 5, 6, 7]
26+
>>> sliding_window_maximum([9, 11], 2)
27+
[11]
28+
>>> sliding_window_maximum([], 3)
29+
[]
30+
>>> sliding_window_maximum([4, 2, 12, 3], 1)
31+
[4, 2, 12, 3]
32+
>>> sliding_window_maximum([1], 1)
33+
[1]
34+
"""
35+
if window_size <= 0:
36+
raise ValueError("Window size must be a positive integer")
37+
if not numbers:
38+
return []
39+
40+
result: list[int] = []
41+
index_deque: deque[int] = deque()
42+
43+
for current_index, current_value in enumerate(numbers):
44+
# Remove the element which is out of this window
45+
if index_deque and index_deque[0] == current_index - window_size:
46+
index_deque.popleft()
47+
48+
# Remove useless elements (smaller than current) from back
49+
while index_deque and numbers[index_deque[-1]] < current_value:
50+
index_deque.pop()
51+
52+
index_deque.append(current_index)
53+
54+
# Start adding to result once we have a full window
55+
if current_index >= window_size - 1:
56+
result.append(numbers[index_deque[0]])
57+
58+
return result

0 commit comments

Comments
 (0)