Skip to main content

Sliding Window

Status

This note is complete, reviewed, and considered stable.

The Sliding Window technique is a powerful algorithmic pattern where we use a "window" (a subset of consecutive elements) that slides over a collection, such as an array or string. By maintaining this window and updating it as we move, we can solve complex range-based problems with optimal efficiency.

This approach allows us to reduce time complexity from nested loops (O(n²)) to linear time (O(n)) by avoiding redundant calculations.

How It Works​

We maintain two pointers that define the boundaries of our window. As we slide the window across the data:

  1. Expand: We move the right pointer to include new elements in our window.
  2. Process: We update our current state (e.g., sum, count, or frequency map) with the new element.
  3. Contract: If our window violates a specific constraint, we move the left pointer to shrink the window until the constraint is met again.

Types of Sliding Windows​

Fixed-Size Window​

In this scenario, our window maintains a constant length k as it moves from start to end.

  • Example: Finding the maximum sum of any subarray of size k.

Dynamic-Sized Window​

The size of our window grows or shrinks dynamically based on the problem's constraints.

  • Example: Finding the smallest subarray whose sum is greater than or equal to a target value x.

Time and Space Complexity​

  • Time Complexity: We typically achieve O(n) because each element is added to and removed from the window at most once.
  • Space Complexity: This varies. If we only track a sum or count, it's O(1). If we use a hash map or set to track frequencies or unique elements, it can be O(k) or O(n).

Common Problems and Examples​

Problem TypeDescriptionExample
Fixed Subarray SumFind the maximum or minimum sum in any window of size k.Max Sum Subarray
Shortest/Longest RangeFind a subarray meeting constraints with minimal or maximal length.Smallest Subarray Sum
Unique ElementsFind windows containing only distinct characters or elements.Longest Unique Substring
Frequency TrackingCount or analyze occurrences within a moving window.Distinct Element Counts

Example 1: Maximum Sum of Subarray of Size k (Fixed-Size)​

We calculate the initial window sum and then "slide" it by adding the next element and subtracting the one that fell out of the window.

def max_sum_subarray(arr, k):
n = len(arr)
if n < k:
return -1

# Initial window sum
window_sum = sum(arr[:k])
max_sum = window_sum

# Slide the window across the rest of the array
for i in range(k, n):
# Add the new element, remove the oldest one
window_sum += arr[i] - arr[i - k]
max_sum = max(max_sum, window_sum)

return max_sum

Example 2: Smallest Subarray with Sum ≥ x (Dynamic-Sized)​

We expand the window until the sum meets our requirement, then shrink it from the left to find the smallest possible valid window.

def min_subarray_len(arr, x):
n = len(arr)
min_len = float('inf')
current_sum = 0
left = 0

for right in range(n):
current_sum += arr[right]

# Shrink the window as long as it remains valid
while current_sum >= x:
min_len = min(min_len, right - left + 1)
current_sum -= arr[left]
left += 1

return min_len if min_len != float('inf') else 0

Example 3: Longest Substring Without Repeating Characters​

We use a set to track elements in our current window and shrink the window whenever we encounter a duplicate.

def longest_unique_substring(s):
char_set = set()
left = 0
max_length = 0

for right in range(len(s)):
# If we find a duplicate, shrink from the left
while s[right] in char_set:
char_set.remove(s[left])
left += 1

char_set.add(s[right])
max_length = max(max_length, right - left + 1)

return max_length

Advantages of the Technique​

  1. Performance: We eliminate the need for O(n²) nested loops in most range-based problems.
  2. Scalability: Our solutions handle large datasets efficiently due to the linear time complexity.
  3. Simplicity: Once we understand the expand/contract logic, it becomes a very intuitive way to process sequential data.

When to Use It​

  • When we need to find a subarray or substring that satisfies a specific condition.
  • When we are tasked with finding the maximum, minimum, or optimal range of elements.
  • When we need to perform running calculations (sums, averages, frequencies) over a moving range.