Engineered
Algorithm Patterns

Sliding Window

Learn how the sliding window pattern tracks contiguous ranges in arrays and strings while avoiding repeated work and quadratic nested loops.

Sliding Window

The sliding window pattern keeps track of a continuous part of an array or string. The window moves across the input as one unit while we update only the values that enter or leave it.

A window can be represented by two indexes, a running total, a substring, or another small data structure. It usually moves from left to right:

Sliding windows are useful when a problem asks about a contiguous range: consecutive array values, neighboring characters, or a substring.

Core idea

When a window moves by one position, do not calculate the whole window again. Remove the value leaving the window and add the value entering it.

When this pattern fits

Look for a sliding window when:

  • The problem asks about a subarray, substring, or other contiguous range.
  • The window has a fixed size, such as “the largest sum of n consecutive values.”
  • The window has a changing size controlled by a condition, such as “the longest substring without duplicates.”
  • The next window overlaps most of the current window.

The values do not need to be sorted. Unlike two pointers, this pattern is about maintaining a moving range and reusing work from the previous range.

Example: maximum sum of consecutive values

Write a function called maxSubarraySum that accepts an array of integers and a number n. Return the largest sum of n consecutive values. If the input is empty or n is larger than the array, return null.

maxSubarraySum([2, 6, 9, 2, 1, 8, 5, 6, 3], 3)  → 19 ([8,5,6])
maxSubarraySum([4, 2, 1, 6], 4)                 → 13 (array length === 4)
maxSubarraySum([], 3)                           → null

The naive approach

The direct solution starts a new inner loop for every possible window:

function maxSubarraySumNaive(numbers, size) {
  if (numbers.length === 0 || size > numbers.length) return null;

  let maximum = -Infinity;

  for (let start = 0; start <= numbers.length - size; start++) {
    let current = 0;

    for (let offset = 0; offset < size; offset++) {
      current += numbers[start + offset];
    }

    maximum = Math.max(maximum, current);
  }

  return maximum;
}

If the array has length n and the requested window has size k, this repeats up to k additions for each starting position. Its time complexity is O(n × k), commonly described as quadratic O(n²) when both values grow with the input.

Build the first window

Start by adding the first size values. For [2, 6, 9, 2, 1, 8, 5, 6, 3] and a window size of 3, the first window is:

[2, 6, 9]  → 17

To move the window one position, subtract the value leaving on the left and add the value entering on the right:

[2, 6, 9] → [6, 9, 2]
17 - 2 + 2 = 17

[6, 9, 2] → [9, 2, 1]
17 - 6 + 1 = 12

The old values are not added again. Each slide performs only one subtraction and one addition.

The sliding-window solution

function maxSubarraySum(numbers, size) {
  if (numbers.length === 0 || size > numbers.length) return null;

  let windowSum = 0;

  for (let i = 0; i < size; i++) {
    windowSum += numbers[i];
  }

  let maximum = windowSum;

  for (let end = size; end < numbers.length; end++) {
    const start = end - size;
    windowSum += numbers[end] - numbers[start];
    maximum = Math.max(maximum, windowSum);
  }

  return maximum;
}

The first loop creates the initial window. The second loop slides it across the remaining values. Every array item is added once and removed once, so the total time is O(n) and the extra space is O(1).

maximum starts at the first real window sum instead of 0. This matters when all values are negative: the answer should remain negative rather than incorrectly becoming zero.

Variable-size windows

Not every window has a fixed size. Sometimes the window grows until it violates a condition, then shrinks from the left until it becomes valid again.

Longest substring without repeated characters

For the string "hellothere", the goal is to find the longest contiguous substring with no repeated character. A set stores the characters currently inside the window:

function longestUniqueSubstring(text) {
  const window = new Set();
  let left = 0;
  let longest = 0;

  for (let right = 0; right < text.length; right++) {
    while (window.has(text[right])) {
      window.delete(text[left]);
      left++;
    }

    window.add(text[right]);
    longest = Math.max(longest, right - left + 1);
  }

  return longest;
}

The right pointer expands the window. When it would add a duplicate, the left pointer removes characters until the window is valid again. Although the code contains a for loop and a while loop, each character enters and leaves the window at most once, so the total time is still O(n).

Fixed and variable windows

Window typeHow it movesTypical problem
Fixed sizeAdd one value and remove one value on every slideMaximum sum of k consecutive values
Variable sizeExpand and shrink until a condition is satisfiedLongest substring without repeated characters
Condition-basedGrow, shrink, or reset based on a running total or countSmallest range with a required sum

The window should represent exactly the part of the input that is currently being evaluated. Keeping that invariant clear makes it easier to decide what to add, what to remove, and when to update the answer.

Sliding window vs. repeated recalculation

ApproachMain methodTypical timeExtra space
Recalculate each rangeSum or inspect every item for every new windowO(n²)O(1)
Sliding windowReuse the previous range and update its edgesO(n)O(1) or O(k)

For a variable-size window, a set or map may be needed to track the current contents, so space can grow with the window size.

Pattern checklist

Ask three questions: Is the target data contiguous? What information describes the current window? When the window moves, which value leaves and which value enters? If you can update the answer from those edge changes, a sliding window is likely a good fit.


Key Takeaways

  • Reuse Over Recalculate: Update only the values entering and leaving the window instead of recalculating the entire range from scratch.
  • Contiguous Data: Works on consecutive elements, subarrays, or substrings—the data does not need to be sorted.
  • Fixed vs. Variable Windows: Use fixed-size windows for exact lengths (like max sum of kk items) and variable-size windows (expand right, shrink left) for condition-based targets.
  • Linear Time: Runs in O(n)O(n) time because every element enters and leaves the window at most once.
  • When to Choose: Use Sliding Window when dealing with contiguous ranges. If you need sorted pairs across opposite ends, use Two Pointers; if order does not matter, use a Frequency Counter.

How is this lesson?