Sliding window pattern for coding interviews - Java code on screen

Master the Sliding Window Pattern for 2026 Interviews

Why the Sliding Window Pattern Matters in 2026 Interviews

If you’re preparing for coding interviews in 2026, the sliding window pattern should be near the top of your study list. It appears in roughly 15–20% of array and string problems on LeetCode, and interviewers at FAANG companies love it because it tests your ability to optimize brute-force solutions into elegant O(n) algorithms.

The core idea is simple: instead of recalculating results for every possible subarray or substring from scratch, you maintain a “window” that slides across the data, adding one element and removing another at each step. This transforms O(n²) or O(n·k) brute-force approaches into clean linear-time solutions.

In this guide, we’ll walk through the pattern step-by-step with three real Java examples — from a warm-up problem to an interview-level challenge.

Understanding the Two Types of Sliding Windows

Before diving into code, it helps to recognize that sliding window problems come in two flavors:

Fixed-size window: You know the window size k upfront. Think “maximum sum of k consecutive elements” or “average of every contiguous subarray of size k.” The window never grows or shrinks — it just slides.

Variable-size (dynamic) window: The window expands and contracts based on a condition. Problems like “longest substring without repeating characters” or “smallest subarray with sum ≥ target” fall here. You grow the window by advancing the right pointer, and shrink it by advancing the left pointer when a constraint is violated.

Recognizing which type you’re dealing with is half the battle. Once you know, the template almost writes itself.

Example 1: Maximum Sum Subarray of Size K (Fixed Window)

Problem: Given an array of integers and an integer k, find the maximum sum of any contiguous subarray of size k.

This is the classic warm-up. A brute-force approach would compute the sum for each window independently in O(n·k). The sliding window does it in O(n).

public class MaxSumSubarray {
    public static int maxSumSubarray(int[] arr, int k) {
        if (arr == null || arr.length < k) {
            throw new IllegalArgumentException("Array length must be >= k");
        }
        // Compute sum of the first window
        int windowSum = 0;
        for (int i = 0; i < k; i++) {
            windowSum += arr[i];
        }
        int maxSum = windowSum;
        // Slide the window: add the next element, remove the first of the previous window
        for (int i = k; i < arr.length; i++) {
            windowSum += arr[i] - arr[i - k];
            maxSum = Math.max(maxSum, windowSum);
        }
        return maxSum;
    }
    public static void main(String[] args) {
        int[] arr = {2, 1, 5, 1, 3, 2};
        int k = 3;
        System.out.println("Max sum of subarray of size " + k + ": "
                + maxSumSubarray(arr, k)); // Output: 9
    }
}

Key takeaway: We compute the first window’s sum, then for each subsequent position we add the incoming element and subtract the outgoing one. No nested loop required. Time complexity: O(n). Space complexity: O(1).

Example 2: Longest Substring Without Repeating Characters (Variable Window)

Problem: Given a string s, find the length of the longest substring without repeating characters. This is LeetCode #3 and a perennial interview favorite.

Here the window size isn’t fixed. We expand by moving the right pointer, and when we hit a duplicate, we shrink from the left until the window is valid again.

import java.util.HashSet;
import java.util.Set;
public class LongestUniqueSubstring {
    public static int lengthOfLongestSubstring(String s) {
        Set<Character> seen = new HashSet<>();
        int left = 0;
        int maxLength = 0;
        for (int right = 0; right < s.length(); right++) {
            // Shrink window until no duplicate
            while (seen.contains(s.charAt(right))) {
                seen.remove(s.charAt(left));
                left++;
            }
            seen.add(s.charAt(right));
            maxLength = Math.max(maxLength, right - left + 1);
        }
        return maxLength;
    }
    public static void main(String[] args) {
        System.out.println(lengthOfLongestSubstring("abcabcbb")); // 3
        System.out.println(lengthOfLongestSubstring("bbbbb"));    // 1
        System.out.println(lengthOfLongestSubstring("pwwkew"));   // 3
    }
}

What’s happening: The right pointer explores new characters. When a collision occurs, the left pointer advances until the duplicate is evicted. The HashSet tracks the current window’s characters. Both pointers only move forward, so total work across all iterations is O(n).

Pro tip for interviews: You can optimize this further with a HashMap storing each character’s last index, allowing the left pointer to jump directly past the duplicate instead of incrementing one step at a time.

Example 3: Minimum Window Substring (Hard — Variable Window)

Problem: Given strings s and t, find the minimum window in s that contains all characters of t. This is LeetCode #76, rated Hard, and one of the most commonly asked sliding window problems in top-tier interviews.

import java.util.HashMap;
import java.util.Map;
public class MinWindowSubstring {
    public static String minWindow(String s, String t) {
        if (s == null || t == null || s.length() < t.length()) return "";
        // Frequency map for characters in t
        Map<Character, Integer> required = new HashMap<>();
        for (char c : t.toCharArray()) {
            required.merge(c, 1, Integer::sum);
        }
        int left = 0, matched = 0;
        int minLen = Integer.MAX_VALUE, minStart = 0;
        Map<Character, Integer> windowCounts = new HashMap<>();
        for (int right = 0; right < s.length(); right++) {
            char rightChar = s.charAt(right);
            windowCounts.merge(rightChar, 1, Integer::sum);
            // Check if this character's count matches the requirement
            if (required.containsKey(rightChar)
                    && windowCounts.get(rightChar).intValue()
                       == required.get(rightChar).intValue()) {
                matched++;
            }
            // Shrink window while all characters are matched
            while (matched == required.size()) {
                if (right - left + 1 < minLen) {
                    minLen = right - left + 1;
                    minStart = left;
                }
                char leftChar = s.charAt(left);
                windowCounts.merge(leftChar, -1, Integer::sum);
                if (required.containsKey(leftChar)
                        && windowCounts.get(leftChar) < required.get(leftChar)) {
                    matched--;
                }
                left++;
            }
        }
        return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
    }
    public static void main(String[] args) {
        System.out.println(minWindow("ADOBECODEBANC", "ABC")); // "BANC"
        System.out.println(minWindow("a", "a"));                // "a"
        System.out.println(minWindow("a", "aa"));               // ""
    }
}

Breaking it down: We maintain two frequency maps — one for the target string t and one for the current window. The matched counter tracks how many distinct characters have met their required frequency. When all characters are matched, we try to shrink the window from the left to find the minimum valid window.

Time complexity: O(n + m) where n = length of s and m = length of t. Space complexity: O(m) for the frequency maps.

The Sliding Window Template You Can Memorize

After working through these examples, a general pattern emerges. Here’s a template you can internalize:

public ResultType slidingWindow(InputType input) {
    int left = 0;
    // Initialize data structures (HashMap, HashSet, counters)
    for (int right = 0; right < input.length; right++) {
        // 1. EXPAND: Add input[right] to the window state
        // 2. SHRINK: While the window is invalid, remove input[left]
        while (windowIsInvalid()) {
            // Remove input[left] from window state
            left++;
        }
        // 3. UPDATE: Record the best result so far
    }
    return bestResult;
}

The three steps — expand, shrink, update — are the heartbeat of every sliding window solution. Fixed-window problems skip the shrink condition (they just check if the window has reached size k). Variable-window problems use the while loop to enforce constraints.

Common Mistakes to Avoid in Interviews

Off-by-one errors: Be deliberate about whether your window boundaries are inclusive or exclusive. Stick with one convention — most Java solutions use inclusive left, inclusive right.

Forgetting edge cases: Empty arrays, k larger than the array, single-element inputs, strings with all identical characters. Always mention these to your interviewer even before coding.

Not recognizing the pattern: If a problem mentions “contiguous subarray,” “substring,” or asks for a maximum/minimum over a range — consider sliding window first. It won’t always apply, but it’s the right instinct.

Overcomplicating the data structure: A HashMap or HashSet is usually sufficient. Resist the urge to use a TreeMap unless the problem specifically requires ordered access.

What to Practice Next

Once you’re comfortable with these three problems, expand your practice with these LeetCode problems that use the same pattern: Permutation in String (#567), Find All Anagrams in a String (#438), Sliding Window Maximum (#239, uses a deque), and Fruit Into Baskets (#904).

The sliding window pattern is one of the highest-ROI topics you can study for 2026 coding interviews. It’s conceptually elegant, it shows up frequently, and once you internalize the expand-shrink-update rhythm, you can solve new variations in minutes rather than struggling for the full interview slot. Build the muscle memory with these examples, and you’ll walk into your next interview with confidence.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *