Problem Statement in English
You’re given an array of integers nums, and an integer k. You need to find the maximum element in every window of size k in the array.
Approach
This is something that unless you’ve seen, you won’t be able to solve.
We use a queue to store the indices of the elements along with their values in the window.
We also ensure that the queue has elements in decreasing order of the values. This allows us to always get the maximum element in the window in constant time.
There are a couple other things to keep in mind, but I think it’s better we work our way through an example to understand the mechanics of this.
$k=2$, nums:
| 7 | 5 | 8 |
ans:
| - | - | - |
q:
| - | - | - |
At $r=0$:
nums:
| 7 | 5 | 8 |
ans:
| - | - | - |
q:
| (0,7) | - | - |
Since the length of q is less than k, we don’t need to remove any elements.
At $r=1$:
nums:
| 7 | 5 | 8 |
ans:
| - | 7 | - |
q:
| (0,7) | (1,5) | - |
Since the length of q is equal to the value of $k$, we need to add something to ans.
At $r=2$:
nums:
| 7 | 5 | 8 |
ans:
| - | 7 | 8 |
q:
| (2,8) |
Since $8 > 5$, which is the rightmost element, we must first remove 5 before appending the new element.
Since the length of q is equal to the value of $k$, we need to add something to ans.
It’s ok if that didn’t make too much sense, try reading the code instead.
Solution in Python
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# if `k` is 1
# we can't have any sliding window
# and so the answer is the same as the input
if k == 1:
# return the input
return nums
# to store the final answer
ans = []
# in this dequeu
# we store a tuple of:
# - the index
# - and the value at that index
q: deque[tuple[int, int]] = deque()
# iterate over the nums
for r in range(nums):
# if the length of the deque is equal to `k`
# we need to remove the oldest element
# because it is no longer in the window
if len(q) == k:
# remove the oldest (leftmost) element
q.popleft()
# while the deque is not empty
# and the last element in the deque
# is less than the current element
# pointed to by the pointer
while len(q) > 0 and q[-1][1] < nums[r]:
# remove the last (rightmost) element
q.pop()
# add the current index along
# with the value at that index to the deque
q.append((r, nums[r]))
# if we've finished the initial loading phase
# where we start with an empty deque
if r >= k - 1:
# and the oldest element is outside the window
while r - q[0][0] >= k:
# remove the oldest element
q.popleft()
# the oldest element is within the window
# so add it to the answer
ans.append(q[0][1])
# return the final answer
return ans
Complexity
Time: $O(n)$
Since we process $n$ elements at most.Space: $O(n)$
Since we store $n$ elements at most in the deque.
Mistakes I Made
I had to look this one up :(
And we are done.