Browse curriculum

Introduction to Sliding Window

Learn how to turn O(N²) brute-force solutions into O(N) by maintaining a dynamic window of elements.

Medium
15 min
Solve on LeetCode

Examples

Input:s = "abcabcbb"
Output:3
Explain:

"abc" is the longest stretch with no repeated character, so the answer is 3.

Input:s = "bbbbb"
Output:1
Explain:

Every character is "b", so no stretch longer than 1 avoids a repeat.

What is the Sliding Window Technique?

The Sliding Window is a technique used to perform operations on a specific subset of data (a window) that moves across a larger dataset (usually an array or string).

Imagine looking at a long train through a small rectangular frame. As the train moves, you see different parts of it, but your frame either keeps its size or expands and contracts. This allows us to process data sequentially without having to re-calculate everything from scratch for every subarray.

The Motivation: Longest Substring

Let's learn this with a classic problem: Longest Substring Without Repeating Characters.

"Given a string s, find the length of the longest substring that contains no duplicate characters."

Example: s = "abcabcbb"

  • abc (Length 3) - Valid
  • abca (Length 4) - Invalid ('a' repeats)
  • bcabc ...

How do we find the maximum length efficiently?

Attempt 1: Brute Force (Why it fails)

The naive approach is to check every possible substring.

  1. Start at index 0 ('a'). Check substrings: 'a', 'ab', 'abc', 'abca'...
  2. Start at index 1 ('b'). Check substrings: 'b', 'bc', 'bca'...

The Problem:

  • Time Complexity: O(N^3) or O(N^2) depending on implementation.
  • Redundant Work: When checking 'abc' then 'abcd', we re-scan 'abc' unnecessarily. We should just ask: "Can we add 'd'?"

When should I use Sliding Window?

Pattern Recognition Triggers:

Use this technique when:

  1. Contiguous: The problem asks for a contiguous subarray or substring.
  2. Running Calculation: You need to calculate something (sum, average, count, max length) over a subset.
  3. Constraints: The input size is large (e.g., 10^5), requiring an O(N) solution.
  4. Keywords: "Longest", "Shortest", "Maximum Sum", "Minimum Length".

The Intuition: Expand and Contract

Instead of starting from scratch, let's treat the substring as a growing and shrinking window.

The Algorithm:

  1. Expand (Right): Extend the window by adding elements one by one.
  2. Validate: Check if the window is currently valid (e.g., no duplicates).
  3. Contract (Left): If invalid, shrink the window from the left until it becomes valid again.
  4. Update: Keep track of the best solution found during valid states.

Interactive Walkthrough

"abcabcbb" · 8 CHARACTERS

EMPTY WINDOW

a

0

b

1

c

2

a

3

b

4

c

5

b

6

b

7

Checks

0

Length

—

Best

0

seen (last index)

Nothing seen yet

 

The window starts empty at index 0, with no characters seen

Next

Read 'a' at 0

String

Legend & Complexity

Solid frame: the current window or substring, with no repeat

Dashed frame: it repeats a character

The earlier copy of the repeated character

Sliding window: characters left behind by L

The longest substring found

Every substring

O(n²)

Sliding window

O(n)

Space

O(min(n, charset))

In Sliding window mode, left and right define the window: each character is read once, and left jumps straight past a repeat. Switch to Check every substring to watch the brute force grow a substring from every start instead. Checks counts the characters each method examines.

Dry Run Table

Step Window Seen Map Action
1 [a] {a:0} Expand R. Valid. Max=1.
2 [a, b] {a:0, b:1} Expand R. Valid. Max=2.
3 [a, b, c] {a:0, b:1, c:2} Expand R. Valid. Max=3.
4 [a, b, c, a] {a:3...} Duplicate 'a'! Invalid.
5 [b, c, a] {a:3, b:1, c:2} Contract L past old 'a' (index 0). New Start=1. Valid.

The Solution Template

Most sliding window problems follow this exact pattern. Memorize it.

def sliding_window(data):
    left = 0
    current_window = ... # Map, Set, or Sum var
    best_answer = ...

    for right in range(len(data)):
        # 1. EXPAND: Add data[right] to window
        add_to_window(data[right])

        # 2. CONTRACT: While window is invalid
        while condition_broken():
            remove_from_window(data[left])
            left += 1
        
        # 3. PROCESS: Update answer if valid
        best_answer = max(best_answer, right - left + 1)

    return best_answer
Introduction to Sliding Window Code
1var lengthOfLongestSubstring = function(s) {
2 let seen = new Map();
3 let left = 0;
4 let maxLen = 0;
5
6 for (let right = 0; right < s.length; right++) {
7 let char = s[right];
8 if (seen.has(char) && seen.get(char) >= left) {
9 left = seen.get(char) + 1;
10 }
11 seen.set(char, right);
12 maxLen = Math.max(maxLen, right - left + 1);
13 }
14 return maxLen;
15};

Edge Cases & Common Mistakes

Edge Case Checklist:

  • Empty String/Array: Always handle input size 0 or 1.
  • K > N: If the problem asks for a window of size K, handle cases where N < K.
  • No Solution: Determine what to return if no valid window exists (e.g. 0, infinity, or empty string).

Common Mistakes:

  • Off-by-one: Be careful with window size calculation (right - left + 1 vs right - left).
  • Shrinking Loop: Using if instead of while to shrink the window. You must keep shrinking until the window becomes valid again.
  • Update Order: Updating the result variable (max/min) at the wrong time (e.g., before checking validity).

Summary

Recap:

  • The Trick: Avoid re-calculating overlapping sub-problems.
  • Movement: Expand right to find potential matches. Contract left to satisfy constraints.
  • Efficiency: Transforms nested loops O(N²) into a linear O(N) single pass.

The approach, step by step

  1. Extend the window

    Move right forward and add the new element to the window’s state.

  2. Restore the rule

    If the window now breaks the condition, move left forward until it holds again.

  3. Record the answer

    Update the best result from the valid window, and return it after the last element.

Frequently asked questions

What is the sliding window technique?

Two indices, left and right, mark a contiguous window over an array or string. The right edge extends one element at a time and the left edge moves forward only when the window breaks a rule, so the window’s state is updated instead of recomputed.


Why is a sliding window O(n)?

Each element enters the window once when right reaches it and leaves at most once when left passes it. However the inner work is arranged, the two pointers make at most 2n moves in total.


When should I use a sliding window?

When a problem asks for the longest, shortest or best contiguous subarray or substring that satisfies a condition, or for a statistic over every window of a fixed size k.

Want to see the mechanism first? Step through it in the visualizer:

Sliding Window

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description