Skip to content

Commit be5869f

Browse files
Add 'Sliding Window Maximum'
1 parent b114299 commit be5869f

File tree

4 files changed

+90
-1
lines changed

4 files changed

+90
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ A collection of LeetCode solutions
8080

8181
[Serialize and Deserialize Binary Tree](./src/serialize_and_deserialize_binary_tree.py)
8282

83+
[Sliding Window Maximum](./src/sliding_window_maximum.py)
84+
8385
[String Compression](./src/string_compression.py)
8486

8587
[Subtree of Another Tree](./src/two_sum.py)

src/minimum_window_substring.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ def minWindow(self, s: str, t: str) -> str:
5050
left += 1
5151
right += 1
5252

53-
return s[start:end + 1] if minimum_size < sys.maxsize else ""
53+
return s[start : end + 1] if minimum_size < sys.maxsize else ""

src/sliding_window_maximum.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
239. Sliding Window Maximum
3+
4+
https://leetcode.com/problems/sliding-window-maximum
5+
6+
NOTES
7+
* Use a sliding window and monotonic queue.
8+
9+
Old fren. I got this one in an Amazon OA. Here is my analysis adapted for the
10+
'Sliding Window Maximum' problem:
11+
12+
This problem can be solved in linear time (O(n)) using a monotonic queue (or
13+
monotone priority queue), a variant of a priority queue in which the priorities
14+
of extracted items are required to form a monotonic sequence:
15+
16+
For all n ∈ N,
17+
n+1 ≥ n for monotonically increasing
18+
n+1 ≤ n for monotonically decreasing
19+
20+
Using a monotonically decreasing queue, the index of the maximum value for the
21+
current window under consideration is maintained at the front of the queue. For
22+
each subsequent value i in `nums`, we remove any elements from the back of the
23+
queue whose corresponding value is smaller than `nums[i]`. This maintains the
24+
monotonically decreasing property of the queue and `q[0]` is always the index
25+
of the largest integer in `nums` for the sliding window. When the indices of
26+
the window change (e.g., when the left index is increased by one), if the
27+
element at the front of the queue falls outside the window, it is removed.
28+
29+
If a monotonically decreasing queue is not used, the maximum integer would need
30+
to be calculated for each window, which requires a double-nested loop that
31+
scales with n.
32+
33+
**NOTE**: While there is a nested loop in this solution as well, the total
34+
number of operations across all iterations of the inner loop is bounded by
35+
O(n). This is known as amortized analysis - even though there's a nested loop,
36+
the total work done by that inner loop across all iterations of the outer loop
37+
is linear.
38+
"""
39+
40+
from collections import deque
41+
42+
43+
class Solution:
44+
def maxSlidingWindow(self, nums: list[int], k: int) -> list[int]:
45+
left, right = 0, 0
46+
47+
# Maintain a monotonically decreasing queue of maximum size k. The
48+
# index of the largest integer in `nums` for the sliding window is
49+
# q[0].
50+
q: deque[int] = deque()
51+
l: list[int] = []
52+
53+
while right < len(nums):
54+
while q and nums[right] > nums[q[-1]]:
55+
q.pop()
56+
q.append(right)
57+
if right >= k - 1:
58+
l.append(nums[q[0]])
59+
if q[0] <= left:
60+
q.popleft()
61+
left += 1
62+
right += 1
63+
64+
return l

tests/test_sliding_window_maximum.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
239. Sliding Window Maximum
3+
4+
https://leetcode.com/problems/sliding-window-maximum
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.sliding_window_maximum import Solution
10+
11+
12+
class TestSolution(TestCase):
13+
def test_1(self):
14+
exp = [3, 3, 5, 5, 6, 7]
15+
assert Solution().maxSlidingWindow([1, 3, -1, -3, 5, 3, 6, 7], 3) == exp
16+
17+
def test_2(self):
18+
exp = [1]
19+
assert Solution().maxSlidingWindow([1], 1) == exp
20+
21+
def test_3(self):
22+
exp = [1, -1]
23+
assert Solution().maxSlidingWindow([1, -1], 1) == exp

0 commit comments

Comments
 (0)