Arrays & Strings6 min read

Sliding Window

A picture frame scanning over an array to solve sub-array problems in \(O(n)\) time
time: \(O(n)\)space: \(O(1)\)

A "subarray" is a contiguous slice of an array. If you need to find the maximum sum of any 3 consecutive numbers in an array, the naive approach is to check every possible group of 3. You start at index 0, check 0-1-2. Then start at index 1, check 1-2-3. Then start at index 2, check 2-3-4. You end up calculating the same middle numbers over and over again. This can lead to an \(O(n*k)\) time complexity.

The Sliding Window technique avoids this repetitive work. Imagine a physical picture frame (a "window") placed over the first 3 numbers. To move the window forward, you don't rebuild the whole frame. You simply subtract the number that falls out of the left side and add the new number that enters the right side. This turns the process into a blazingly fast \(O(n)\) scan!

Watch the window slide

← → arrow keys to step · click elements to interact

Fixed-Size Sliding Window: Max Sum

def max_sum_subarray(arr, k):
"""Maximum sum of any contiguous subarray of length k."""
n = len(arr)
if n < k: return None
# Build first window
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, n):
window_sum += arr[i] - arr[i - k] # slide right
max_sum = max(max_sum, window_sum)
return max_sum
print(max_sum_subarray([2, 1, 5, 1, 3, 2], 3)) # 9 (5+1+3)
print(max_sum_subarray([2, 3, 4, 1, 5], 2)) # 7 (3+4)
Output
9
7

Pattern 1: Fixed-size Window

This is when the problem gives you a specific size (e.g., "find the max sum of exactly *k* elements").

  1. First, calculate the sum/result for the very first window of size k.
  2. Record this as the best/maximum result so far.
  3. Start a loop from k to the end of the array.
  4. At each step, take your previous result, add the new element arr[i], and subtract the old element arr[i-k]. Update the max result if necessary.

Pattern 2: Dynamically-sized Window

Sometimes the window size isn't fixed. The problem might ask "find the smallest contiguous subarray whose sum is greater than or equal to S". Here, the window grows and shrinks like an accordion.

You still use a left and right pointer:

  • Expand the window by moving right forward, adding each new number to a running sum.
  • When the running sum meets the condition (e.g., >= S), try to make the window as small as possible by moving the left pointer forward (and subtracting those values), recording the window length each time.
  • When the condition breaks, go back to expanding with the right pointer.

Even though there is a while loop inside a for loop, both the left and right pointers only move forward, meaning every element is processed at most twice. The time complexity stays \(O(n)\)! This is closely related to the two pointer technique.

Note: Sliding Window only works on contiguous elements (subarrays or substrings). If the problem asks for "subsequences" (where elements don't have to be next to each other), Sliding Window is not the right tool!

Complexity

Time ComplexityEach element is processed at most twice (enters and leaves the window)
Linear\(O(n)\)
Space ComplexityOnly requires tracking the pointers and a running sum/hash map
Constant\(O(1)\)

Variable-Size Sliding Window: Longest Substring Without Repeating

def longest_unique(s):
"""Longest substring without repeating characters."""
seen = {}
lo = 0
max_len = 0
for hi, ch in enumerate(s):
if ch in seen and seen[ch] >= lo:
lo = seen[ch] + 1 # shrink window
seen[ch] = hi
max_len = max(max_len, hi - lo + 1)
return max_len
print(longest_unique('abcabcbb')) # 3 ('abc')
print(longest_unique('bbbbb')) # 1 ('b')
print(longest_unique('pwwkew')) # 3 ('wke')
Output
3
1
3
Challenge

Quick check

What kind of problems is the Sliding Window technique best suited for?

Continue reading

Two Pointers
Two fingers tracing an array to solve problems in one pass
Prefix Sums
Pre-calculate a running total so you can sum any subarray in instant \(O(1)\) time
Static Arrays
A row of numbered boxes — fast to grab, fixed in size
Design a Rate LimiterSystem Design
Protect your API from being overwhelmed