|
| 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 |
0 commit comments