Skip to content

Sliding Window Pattern

Overview

Maintain a "window" over a portion of data that slides through to find optimal subarrays/substrings satisfying certain conditions.

When to Use

  • Find max/min subarray of size K
  • Longest/shortest substring with specific property
  • Subarray with given sum
  • String permutation/anagram problems
  • Contiguous sequence problems

Sliding Window Step-by-Step

Window Types: - Fixed Window: Maintain exact size K, slide by adding right and removing left - Variable Window: Expand right to grow, contract left when invalid

Template Code

Fixed Size Window - Max Sum of K Elements

public int maxSumSubarray(int[] nums, int k) {
    int windowSum = 0;
    int maxSum = Integer.MIN_VALUE;

    for (int i = 0; i < nums.length; i++) {
        windowSum += nums[i];  // Add right element

        if (i >= k - 1) {  // Window is full
            maxSum = Math.max(maxSum, windowSum);
            windowSum -= nums[i - k + 1];  // Remove left element
        }
    }
    return maxSum;
}

Variable Window - Minimum Size Subarray Sum

public int minSubArrayLen(int target, int[] nums) {
    int left = 0;
    int sum = 0;
    int minLength = Integer.MAX_VALUE;

    for (int right = 0; right < nums.length; right++) {
        sum += nums[right];  // Expand window

        while (sum >= target) {  // Shrink while valid
            minLength = Math.min(minLength, right - left + 1);
            sum -= nums[left];
            left++;
        }
    }
    return minLength == Integer.MAX_VALUE ? 0 : minLength;
}

Longest Substring Without Repeating Characters

public int lengthOfLongestSubstring(String s) {
    Map<Character, Integer> charIndex = new HashMap<>();
    int maxLength = 0;
    int left = 0;

    for (int right = 0; right < s.length(); right++) {
        char c = s.charAt(right);

        if (charIndex.containsKey(c) && charIndex.get(c) >= left) {
            left = charIndex.get(c) + 1;  // Jump past duplicate
        }

        charIndex.put(c, right);
        maxLength = Math.max(maxLength, right - left + 1);
    }
    return maxLength;
}

Longest Substring with K Distinct Characters

public int lengthOfLongestSubstringKDistinct(String s, int k) {
    Map<Character, Integer> charCount = new HashMap<>();
    int maxLength = 0;
    int left = 0;

    for (int right = 0; right < s.length(); right++) {
        char c = s.charAt(right);
        charCount.put(c, charCount.getOrDefault(c, 0) + 1);

        while (charCount.size() > k) {  // Too many distinct
            char leftChar = s.charAt(left);
            charCount.put(leftChar, charCount.get(leftChar) - 1);
            if (charCount.get(leftChar) == 0) {
                charCount.remove(leftChar);
            }
            left++;
        }

        maxLength = Math.max(maxLength, right - left + 1);
    }
    return maxLength;
}

Find All Anagrams in String

public List<Integer> findAnagrams(String s, String p) {
    List<Integer> result = new ArrayList<>();
    if (s.length() < p.length()) return result;

    int[] pCount = new int[26];
    int[] sCount = new int[26];

    // Count pattern characters
    for (char c : p.toCharArray()) {
        pCount[c - 'a']++;
    }

    for (int i = 0; i < s.length(); i++) {
        sCount[s.charAt(i) - 'a']++;  // Add right

        if (i >= p.length()) {
            sCount[s.charAt(i - p.length()) - 'a']--;  // Remove left
        }

        if (i >= p.length() - 1 && Arrays.equals(pCount, sCount)) {
            result.add(i - p.length() + 1);
        }
    }
    return result;
}

Minimum Window Substring

public String minWindow(String s, String t) {
    if (s.length() < t.length()) return "";

    Map<Character, Integer> need = new HashMap<>();
    Map<Character, Integer> have = new HashMap<>();

    for (char c : t.toCharArray()) {
        need.put(c, need.getOrDefault(c, 0) + 1);
    }

    int required = need.size();
    int formed = 0;
    int left = 0;
    int minLen = Integer.MAX_VALUE;
    int minStart = 0;

    for (int right = 0; right < s.length(); right++) {
        char c = s.charAt(right);
        have.put(c, have.getOrDefault(c, 0) + 1);

        if (need.containsKey(c) && have.get(c).equals(need.get(c))) {
            formed++;
        }

        while (formed == required) {  // Valid window, try to shrink
            if (right - left + 1 < minLen) {
                minLen = right - left + 1;
                minStart = left;
            }

            char leftChar = s.charAt(left);
            have.put(leftChar, have.get(leftChar) - 1);

            if (need.containsKey(leftChar) &&
                have.get(leftChar) < need.get(leftChar)) {
                formed--;
            }
            left++;
        }
    }

    return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
}

Sliding Window Maximum (with Deque)

public int[] maxSlidingWindow(int[] nums, int k) {
    int[] result = new int[nums.length - k + 1];
    Deque<Integer> deque = new ArrayDeque<>();  // Stores indices

    for (int i = 0; i < nums.length; i++) {
        // Remove elements outside window
        while (!deque.isEmpty() && deque.peekFirst() < i - k + 1) {
            deque.pollFirst();
        }

        // Remove smaller elements (they'll never be max)
        while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
            deque.pollLast();
        }

        deque.offerLast(i);

        if (i >= k - 1) {
            result[i - k + 1] = nums[deque.peekFirst()];
        }
    }
    return result;
}

Time & Space Complexity

Problem Time Space
Fixed window max sum O(n) O(1)
Min subarray sum O(n) O(1)
Longest without repeat O(n) O(min(n,m))
K distinct chars O(n) O(k)
Find anagrams O(n) O(1)
Min window substring O(n+m) O(m)
Sliding window max O(n) O(k)

Common Interview Questions

  1. Maximum Sum Subarray of Size K - Fixed window
  2. Minimum Size Subarray Sum - Variable window ≥ target
  3. Longest Substring Without Repeating Characters - Classic
  4. Longest Substring with At Most K Distinct Characters - Variable
  5. Fruit Into Baskets - Same as K=2 distinct
  6. Permutation in String - Check if s2 contains permutation of s1
  7. Find All Anagrams in a String - Return all start indices
  8. Minimum Window Substring - Smallest window containing all chars
  9. Sliding Window Maximum - Max in each window of size K
  10. Substring with Concatenation of All Words - Complex anagram
  11. Longest Repeating Character Replacement - With K replacements
  12. Max Consecutive Ones III - With K flips allowed
  13. Subarrays with K Different Integers - Exactly K distinct

Tips & Tricks

  • Fixed window: expand until size K, then slide (add right, remove left)
  • Variable window: expand right, contract left when invalid
  • Use HashMap for character frequency tracking
  • Use Deque for monotonic window (max/min in window)
  • "At most K" - "At most K-1" = "Exactly K" trick
  • Always track window state incrementally, don't recompute