Sliding Window Maximum Using Deque in DSA Typescript - Time & Space Complexity
We want to understand how the time needed changes when finding the maximum in each sliding window of an array using a deque.
How does the number of steps grow as the array and window size grow?
Analyze the time complexity of the following code snippet.
function maxSlidingWindow(nums: number[], k: number): number[] {
const deque: number[] = []
const result: number[] = []
for (let i = 0; i < nums.length; i++) {
while (deque.length && nums[deque[deque.length - 1]] <= nums[i]) {
deque.pop()
}
deque.push(i)
if (deque[0] === i - k) {
deque.shift()
}
if (i >= k - 1) {
result.push(nums[deque[0]])
}
}
return result
}
This code finds the maximum value in every window of size k as it slides over the array.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: A single loop over the array elements.
- How many times: Each element is visited once, and each index is added and removed from the deque at most once.
As the array size grows, the number of operations grows roughly in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 operations (each element pushed and popped once) |
| 100 | About 200 operations |
| 1000 | About 2000 operations |
Pattern observation: The operations grow linearly with input size, not more.
Time Complexity: O(n)
This means the time needed grows directly with the number of elements in the array.
[X] Wrong: "Because of the nested while loop, the time complexity is O(n*k)."
[OK] Correct: Each element is pushed and popped at most once, so the inner loop does not run for every element repeatedly. The total work is still proportional to n.
Understanding this linear time solution shows you can optimize sliding window problems efficiently, a skill valued in many coding challenges.
What if we changed the data structure from a deque to a simple array for storing indices? How would the time complexity change?
Practice
Solution
Step 1: Understand the role of deque in the algorithm
The deque stores indices of elements in the current window, maintaining them in decreasing order of their values to quickly find the maximum.Step 2: Eliminate incorrect options
Options A, B, and C do not describe the deque's role in maintaining order or tracking maximums.Final Answer:
To keep track of indices of elements in the current window in decreasing order of their values -> Option DQuick Check:
Deque stores indices in decreasing order = D [OK]
- Thinking deque stores actual values instead of indices
- Assuming deque sorts the entire array
- Confusing deque with a stack or queue only
Solution
Step 1: Identify correct deque initialization in TypeScript
Using an array of numbers is the common way to simulate a deque for indices, soconst deque: number[] = [];is correct.Step 2: Check other options for errors
A pushes null which is incorrect, B uses a non-existent Deque class by default, and D uses string array which is wrong for indices.Final Answer:
const deque: number[] = []; -> Option AQuick Check:
Array of numbers for deque = C [OK]
- Using string array instead of number array
- Trying to use a Deque class without importing
- Pushing null or undefined initially
function maxSlidingWindow(nums: number[], k: number): number[] {
const deque: number[] = [];
const result: number[] = [];
for (let i = 0; i < nums.length; i++) {
while (deque.length && nums[deque[deque.length - 1]] <= nums[i]) {
deque.pop();
}
deque.push(i);
if (deque[0] === i - k) {
deque.shift();
}
if (i >= k - 1) {
result.push(nums[deque[0]]);
}
}
return result;
}
console.log(maxSlidingWindow([1,3,-1,-3,5,3,6,7], 3));Solution
Step 1: Trace the sliding window maximum for each window
Windows and their max values: [1,3,-1] -> 3 [3,-1,-3] -> 3 [-1,-3,5] -> 5 [-3,5,3] -> 5 [5,3,6] -> 6 [3,6,7] -> 7Step 2: Confirm the output array matches these max values
The output array is [3, 3, 5, 5, 6, 7], which matches.Final Answer:
[3, 3, 5, 5, 6, 7] -> Option BQuick Check:
Sliding window max = [3,3,5,5,6,7] [OK]
- Not removing indices outside the window
- Incorrectly popping from deque
- Mixing values and indices in deque
function maxSlidingWindow(nums: number[], k: number): number[] {
const deque: number[] = [];
const result: number[] = [];
for (let i = 0; i < nums.length; i++) {
while (deque.length && nums[deque[deque.length - 1]] < nums[i]) {
deque.pop();
}
deque.push(i);
if (deque[0] <= i - k) {
deque.shift();
}
if (i >= k - 1) {
result.push(nums[deque[0]]);
}
}
return result;
}Solution
Step 1: Analyze the while loop condition
The condition 'nums[deque[deque.length - 1]] < nums[i]' does not pop elements equal to nums[i], keeping redundant candidates. It should use '<=' for strictly decreasing order.Step 2: Check other options
B would fail to remove exactly expired indices, C removes necessary logic, D reverses order incorrectly.Final Answer:
Change condition to 'nums[deque[deque.length - 1]] <= nums[i]' in while loop -> Option AQuick Check:
<= in while removes equals too [OK]
- Using < instead of <= in while loop
- Wrong fix changing shift condition to <
- Using unshift instead of push
nums = [4, 2, 12, 3, 8, 7, 9] and window size k = 4, what is the sliding window maximum output if the algorithm is modified to return the indices of maximum elements instead of values?Solution
Step 1: Find max values and their indices for each window of size 4
Windows and max indices: [4,2,12,3] (0-3) -> 2 (12) [2,12,3,8] (1-4) -> 2 (12) [12,3,8,7] (2-5) -> 2 (12) [3,8,7,9] (3-6) -> 6 (9)Step 2: Collect indices of max elements
The indices are [2, 2, 2, 6].Final Answer:
[2, 2, 2, 6] -> Option CQuick Check:
Max indices per window = [2,2,2,6] [OK]
- Returning values instead of indices
- Mixing up indices when max repeats
- Not updating max index when window slides
Ready to prove it?
Pass the test and this pattern moves unknown
