Sliding Window Maximum

Updated on 24 June, 2025
Sliding Window Maximum header image

Problem Statement

In this task, you are provided with an integer array named nums. Alongside the array, there is a sliding window of a given size k which begins at the very start of the array and slides towards the right end, one element at a time. At each position of this sliding window, you are required to determine the maximum value of the k elements within the window. The objective is to return a list containing these maximum values from each window position as the window slides from left to right through the entire array.

Examples

Example 1

Input:

nums = [1,3,-1,-3,5,3,6,7], k = 3

Output:

[3,3,5,5,6,7]

Explanation:

Window positions and max values:
[1 3 -1] -3  5  3  6  7  → max = 3  
 1 [3 -1 -3] 5  3  6  7  → max = 3  
 1  3 [-1 -3 5] 3  6  7  → max = 5  
 1  3 -1 [-3 5 3] 6  7  → max = 5  
 1  3 -1 -3 [5 3 6] 7  → max = 6  
 1  3 -1 -3  5 [3 6 7] → max = 7

Example 2

Input:

nums = [1], k = 1

Output:

[1]

Explanation:

Only one window of size 1 → max = 1

Constraints

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

Approach and Intuition

To solve this efficiently, we use a deque (double-ended queue) to maintain a list of indices whose corresponding values are potential maximums for the current window. Here’s the reasoning:

  1. Track Useful Indices Only:

    • As we iterate over nums, we remove indices from the back of the deque if their value is less than the current element (they can never be the max again).
    • We also remove indices from the front if they fall out of the current window.
  2. Maintain Window Max at Front:

    • The front of the deque always contains the index of the maximum element for the current window.
  3. Build Result:

    • Once the first k elements are processed, we start appending nums[deque[0]] to the result for each window shift.

This approach has a time complexity of O(n), where n is the length of nums, as each index is pushed and popped from the deque at most once. It satisfies the performance constraints while providing accurate maximum values for each window shift.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    vector<int> slidingMaximum(vector<int>& numbers, int windowSize){
        deque<int> indices;
        vector<int> output;
        for (int i = 0; i < windowSize; i++) {
            while (!indices.empty() && numbers[i] >= numbers[indices.back()]) {
                indices.pop_back();
            }
            indices.push_back(i);
        }
        output.push_back(numbers[indices.front()]);

        for (int i = windowSize; i < numbers.size(); i++) {
            if(indices.front() == i - windowSize) {
                indices.pop_front();
            }
            while (!indices.empty() && numbers[i] >= numbers[indices.back()]) {
                indices.pop_back();
            }

            indices.push_back(i);
            output.push_back(numbers[indices.front()]);
        }
        
        return output;
    }
};

The provided C++ code efficiently computes the maximum values in a sliding window over a given array of integers. Implement this code when you need to determine the maximum for every window of size windowSize across the array numbers.

Understand the critical steps the algorithm employs:

  • Utilize a double-ended queue (deque) to store the indices of the array elements. This structure helps manage elements and maintain their order as the window slides across the array.
  • Process the initial window separately to set up the deque correctly.
  • For each subsequent element beyond the initial window, adjust the deque:
    1. Remove the element that slides out of the window.
    2. Maintain the max-heap property by removing elements from the deque which are less than the current element being added.
    3. Add the current element (or its index) to the deque.
    4. The front of the deque always contains the index of the maximum element for the current window, which is then added to the output array.

Use this pattern in scenarios where sliding window maximum calculations are relevant, such as analyzing financial data streams, image processing, or other array manipulation tasks that require efficient real-time computation.

java
class Solution {
    public int[] slidingMaximum(int[] values, int windowSize) {
        Deque<Integer> deque = new ArrayDeque<>();
        List<Integer> maxValues = new ArrayList<>();

        for (int j = 0; j < windowSize; j++) {
            while (!deque.isEmpty() && values[j] >= values[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(j);
        }
        maxValues.add(values[deque.peekFirst()]);

        for (int j = windowSize; j < values.length; j++) {
            if (deque.peekFirst() == j - windowSize) {
                deque.pollFirst();
            }
            while (!deque.isEmpty() && values[j] >= values[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(j);
            maxValues.add(values[deque.peekFirst()]);
        }
        // Convert integer list to array
        return maxValues.stream().mapToInt(i -> i).toArray();
    }
}

The solution provided demonstrates a Java method to find the maximum value in each sliding window of a given size in an array of integers using the sliding window technique and a deque (double-ended queue). Here’s a brief breakdown of how the solution works:

  • Initialize a Deque to store indices of array elements, ensuring the largest element's index remains at the front.
  • Use a loop to handle the first window separately to set up the initial state of the deque.
    • Iterate through each element within the first window size.
    • Maintain elements in decreasing order in the deque by removing elements from the back of the deque which are less than the current element being considered.
    • Add each index to the deque after the older, smaller elements are removed.
  • Add the element corresponding to the current front of the deque to the results list as it represents the maximum of the current window.
  • Process the rest of the array elements beyond the initial window size using another loop:
    • If the index of the current maximum (front of the deque) is outside the current window, remove it from the deque.
    • Similar to the first window setup, if the current element is greater than the elements at the back of the deque, remove those elements.
    • Add the current index to the deque.
    • Append the front value of the deque to the results list, as it represents the maximum for the current window.
  • Convert the list of maximum values found for each sliding window into an integer array using a stream operation before returning it.

This approach ensures each window's maximum is found efficiently, with each element being added and removed from the deque at most once, resulting in linear time complexity relative to the number of elements in the input array.

python
class Solution:
    def slidingMaximum(self, values: List[int], window_size: int) -> List[int]:
        deque_index = deque()
        output = []

        for index in range(window_size):
            while deque_index and values[index] >= values[deque_index[-1]]:
                deque_index.pop()
            deque_index.append(index)

        output.append(values[deque_index[0]])

        for index in range(window_size, len(values)):
            if deque_index and deque_index[0] == index - window_size:
                deque_index.popleft()
            while deque_index and values[index] >= values[deque_index[-1]]:
                deque_index.pop()

            deque_index.append(index)
            output.append(values[deque_index[0]])

        return output

The provided Python solution harnesses the sliding window technique to compute the maximum in each window of a given size in an array using an efficient approach. Below is a concise analysis of how the solution works:

  • Initialize a double-ended queue (deque_index) to store indices and an output list to hold the results.
  • Process the first window_size elements separately:
    1. Iterate through the elements and, for each element, remove indices from deque_index if the current element's value is greater than the value at the indices stored in deque_index.
    2. Append the current index to deque_index.
    3. After processing the first window_size elements, append the value at the front of deque_index to the output.
  • For the remaining elements in the list:
    1. For each element, discard the oldest index from deque_index if it falls out of the current window's range.
    2. Remove indices from deque_index as before if the current element's value is greater than the values at the indices stored.
    3. Append the current index.
    4. Append the value at the front of the deque_index to the output.
  • Ultimately, the output list contains the maximum for each sliding window.

This solution ensures that the queue size is constant relative to the window size, leading to a time complexity of O(n) for processing n elements. The space complexity is O(w) where w is the window size for storing indices of elements in the double-ended queue.

Comments

No comments yet.