Sliding Window Maximum Using Deque in DSA C# - Time & Space Complexity
We want to understand how the time needed to find the maximum in each sliding window changes as the input grows.
How does the algorithm handle many elements efficiently?
Analyze the time complexity of the following code snippet.
public int[] MaxSlidingWindow(int[] nums, int k) {
var result = new int[nums.Length - k + 1];
var deque = new LinkedList<int>();
for (int i = 0; i < nums.Length; i++) {
while (deque.Count > 0 && deque.First.Value <= i - k) deque.RemoveFirst();
while (deque.Count > 0 && nums[deque.Last.Value] < nums[i]) deque.RemoveLast();
deque.AddLast(i);
if (i >= k - 1) result[i - k + 1] = nums[deque.First.Value];
}
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: One main loop runs through all elements once.
- How many times: Each element is added and removed from the deque at most once.
As the input size grows, each element is handled a limited number of times, so work grows roughly in direct proportion to input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 operations (each element added and removed once) |
| 100 | About 200 operations |
| 1000 | About 2000 operations |
Pattern observation: The operations grow linearly with input size.
Time Complexity: O(n)
This means the time needed grows directly with the number of elements in the input.
[X] Wrong: "Because there are nested while loops, the time complexity must be O(n²)."
[OK] Correct: Each element is added and removed from the deque only once, so the total work is still linear, not quadratic.
Understanding this efficient approach shows you can handle sliding window problems smartly, a common skill interviewers look for.
"What if we used a simple array instead of a deque to track maximums? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of deque in sliding window
The deque stores indices of elements in a way that the front always has the index of the maximum element for the current window.Step 2: Why deque helps in O(1) max retrieval
Because the deque maintains elements in decreasing order, the maximum is always at the front, allowing quick access without scanning the window.Final Answer:
To store indices of elements in a way that helps find the maximum in O(1) time -> Option AQuick Check:
Deque stores max indices = To store indices of elements in a way that helps find the maximum in O(1) time [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 the correct data structure for deque in C#
C# does not have a built-in deque class, but LinkedList<T> supports adding/removing from both ends, acting as a deque.Step 2: Why LinkedList is suitable
LinkedList allows efficient insertion and removal from front and back, which is essential for deque operations in sliding window maximum.Final Answer:
var deque = new LinkedList<int>(); -> Option BQuick Check:
LinkedList supports deque operations = var deque = new LinkedList<int>(); [OK]
- Using Queue which only supports FIFO
- Using Stack which only supports LIFO
- Using List which is inefficient for front removals
[2, 1, 3, 4, 6, 3, 8, 9, 10, 12, 56] with window size 4?Solution
Step 1: Slide window and find max for each window of size 4
Windows and max values:
Window 1: [2,1,3,4] max=4
Window 2: [1,3,4,6] max=6
Window 3: [3,4,6,3] max=6
Window 4: [4,6,3,8] max=8
Window 5: [6,3,8,9] max=9
Window 6: [3,8,9,10] max=10
Window 7: [8,9,10,12] max=12
Window 8: [9,10,12,56] max=56Step 2: Write the max values as output array
The output array is [4, 6, 6, 8, 9, 10, 12, 56].Final Answer:
[4, 6, 6, 8, 9, 10, 12, 56] -> Option AQuick Check:
Max per window = [4, 6, 6, 8, 9, 10, 12, 56] [OK]
- Confusing max with last element in window
- Missing last window max
- Off-by-one errors in window sliding
for (int i = 0; i < nums.Length; i++) {
while (deque.Count > 0 && nums[deque.Last.Value] <= nums[i]) {
deque.RemoveLast();
}
deque.AddLast(i);
if (deque.First.Value >= i - k) {
deque.RemoveFirst();
}
if (i >= k - 1) {
result.Add(nums[deque.First.Value]);
}
}Solution
Step 1: Analyze condition for removing front index
The condition 'deque.First.Value >= i - k' removes indices inside the window since valid front indices are >= i - k + 1 which is always true for >= i - k, causing incorrect removal of current max candidates.Step 2: Correct condition to remove outdated indices
Window covers [i-k+1 to i], remove if deque.First.Value < i - k + 1 i.e. deque.First.Value <= i - k.Final Answer:
The condition to remove from front should be <= instead of >= -> Option DQuick Check:
Remove outdated indices with <= i - k condition [OK]
- Using >= instead of <= causes removing valid indices
- Removing from back incorrectly
- Storing values instead of indices in deque
nums = [1,3,-1,-3,5,3,6,7] and window size k = 3, how would you modify the sliding window maximum algorithm using deque to also return the indices of the maximum elements for each window?Solution
Step 1: Understand what deque stores
The deque stores indices of elements, not values, to track positions and efficiently remove outdated indices.Step 2: Output indices of maximum elements
The maximum element's index is always at the front of the deque, so outputting deque.First.Value for each window gives the index of the max element.Final Answer:
Store indices in deque and output deque.First.Value for each window -> Option CQuick Check:
Deque front index = max element index [OK]
- Storing values instead of indices in deque
- Outputting deque.Last.Value instead of First
- Confusing values with indices in output
Ready to prove it?
Pass the test and this pattern moves unknown
