Back to Home

Sliding Windows

Sliding Windows maintain a subarray/subsequence while moving through the input once.
The main decision is always: when to grow and when to shrink.

General Setup

Use a window [l, r):

  • l is inclusive, r is exclusive.
  • Grow by increasing r.
  • Shrink by increasing l.
  • Maintain window data (sum, frequency map, bad-count, distinct-count, etc.).

1) Fixed-Length Windows

Use this when the window size is exactly k.

python
fixed_length_window(arr, k):
    initialize:
        l, r = 0, 0
        window_data
        cur_best
    while r < len(arr):
        grow window with arr[r]; r += 1
        if r - l == k:
            update cur_best
            shrink window from l; l += 1
    return cur_best
Example Problem (Fixed-Length): Most Weekly Sales

Problem

Given an array sales, return the largest total sales across any 7-day period.
If there is no 7-day period, return 0.

Example

sales = [0, 3, 7, 12, 10, 5, 0, 1, 0, 15, 12, 11, 1] → Output: 44

Solution (Python)

python
def most_weekly_sales(sales):
    l = 0
    window_sum = 0
    best = 0

    for r in range(len(sales)):
        window_sum += sales[r]
        if r - l + 1 == 7:
            best = max(best, window_sum)
            window_sum -= sales[l]
            l += 1
    return best

Related practice: Most Sales in K Days

2) Resetting Windows

Use this when adding one element can make the whole window irrecoverably invalid, so shrinking one-by-one is unnecessary.

python
resetting_window(arr):
    initialize:
        l, r = 0, 0
        window_data
        cur_best
    while r < len(arr):
        if window remains valid after adding arr[r]:
            grow window with arr[r]; r += 1
            update cur_best
        else:
            reset window and data structures past the problematic element
    return cur_best
Example Problem (Resetting): Longest Good Day Streak

Problem

Given sales, find the longest consecutive streak with no bad day.
A day is bad if sales[i] < 10.

Example

sales = [0, 14, 7, 12, 10, 20] → Output: 3 (streak [12, 10, 20])

Solution (Python)

python
def longest_good_day_streak(sales):
    l = 0
    best = 0

    for r in range(len(sales)):
        if sales[r] >= 10:
            best = max(best, r - l + 1)
        else:
            l = r + 1
    return best

3) Maximum Windows

Use this when the objective is to maximize window length/value under a constraint.

python
maximum_window(arr):
    initialize:
        l, r = 0, 0
        window_data
        cur_best
    while r < len(arr):
        if can grow and stay valid:
            grow window with arr[r]; r += 1
            update cur_best
        elif l == r:
            l += 1; r += 1
        else:
            shrink window from l; l += 1
    return cur_best
Example Problem (Maximum): Maximum with At Most 3 Bad Days

Problem
Given sales, find the longest consecutive period containing at most 3 bad days (sales[i] < 10).

Example
sales = [0, 14, 7, 9, 0, 20, 10, 0, 10] → Output: 6

Solution (Python)

python
def max_at_most_3_bad_days(sales):
    l = 0
    bad_days = 0
    best = 0

    for r in range(len(sales)):
        if sales[r] < 10:
            bad_days += 1

        while bad_days > 3:
            if sales[l] < 10:
                bad_days -= 1
            l += 1

        best = max(best, r - l + 1)
    return best

Related practice: Longest Substring Without Repeating Characters

4) Minimum Windows

Use this when the objective is to find the shortest window that satisfies a constraint.

python
minimum_window(arr):
    initialize:
        l, r = 0, 0
        window_data
        cur_best = inf
    while True:
        if window must grow to become valid:
            if r == len(arr):
                break
            grow window with arr[r]; r += 1
        else:
            update cur_best
            shrink window from l; l += 1
    return cur_best
Example Problem (Minimum): Shortest Period with Over 20 Sales

Problem
Given sales, return the length of the shortest contiguous period with total sales strictly greater than 20.
If no such period exists, return -1.

Examples
[5, 10, 15, 5, 10]2
[5, 10, 4, 5, 10]4
[5, 5, 5]-1

Solution (Python)

python
def shortest_over_20_sales(sales):
    l = 0
    window_sum = 0
    best = float('inf')

    for r in range(len(sales)):
        window_sum += sales[r]
        while window_sum > 20:
            best = min(best, r - l + 1)
            window_sum -= sales[l]
            l += 1

    return -1 if best == float('inf') else best

Related practice: Minimum Size Subarray Sum

5) Counting Problems (At-Most-K / Exactly-K / At-Least-K)

When the At-Most-K version has the maximum-window property, you can reuse it for other counting forms.

At-Most-K Recipe

python
count_at_most_k(arr, k):
    l = 0
    count = 0
    window_data
    for r in range(len(arr)):
        add arr[r] to window_data
        while invalid(window_data, k):
            remove arr[l] from window_data
            l += 1
        count += r - l + 1
    return count

Reusable transforms

  • Exactly-K = At-Most-K(k) - At-Most-K(k - 1)
  • At-Least-K = TotalSubarrays - At-Most-K(k - 1), where TotalSubarrays = n * (n + 1) / 2

Some counting problems do not fit this transform directly and should be handled case by case.

Example Problem (Counting): Count Subarrays with At Most K Bad Days

Problem
Given sales, count the number of subarrays that contain at most k bad days (sales[i] < 10).

Example
sales = [0, 20, 5], k = 1 → Output: 5

Solution (Python)

python
def count_at_most_k_bad_days(sales, k):
    l = 0
    bad_days = 0
    count = 0

    for r in range(len(sales)):
        if sales[r] < 10:
            bad_days += 1
        while bad_days > k:
            if sales[l] < 10:
                bad_days -= 1
            l += 1
        count += (r - l + 1)

    return count

For Exactly-K bad days:

python
exactly_k = count_at_most_k_bad_days(sales, k) - count_at_most_k_bad_days(sales, k - 1)

For At-Least-K bad days:

python
n = len(sales)
total = n * (n + 1) // 2
at_least_k = total - count_at_most_k_bad_days(sales, k - 1)

Related practice: Count Subarrays with At Most K Bad Days

Key Takeaways

  • Contiguous Subarrays: Sliding windows are primarily used for problems involving contiguous subarrays or substrings.
  • Two Pointers: The technique relies on two pointers (l and r) moving in the same direction (usually left to right).
  • Linear Time: The complexity is typically O(N)O(N) because each element is added and removed from the window at most once.
  • Window Validity: The core logic revolves around maintaining a valid window state:
    • Expand (r++) to include more elements or find a valid window.
    • Shrink (l++) to maintain constraints or minimize the window size.
  • Optimization: Always check if you can calculate the result from the window state in O(1)O(1) time to keep the overall complexity linear.