Minimum Window Substring

HardSliding Window · Dynamic Size🧩 Sliding WindowLeetCode #76 ↗Updated

Problem

Given strings s and t, find the shortest contiguous substring of s that contains every character of t, counting duplicates (if t has two 'a's, the window needs two). Return "" if no such window exists; the answer is guaranteed unique.
Inputs="ADOBECODEBANC", t="ABC"Output"BANC"
Inputs="a", t="a"Output"a"
Inputs="a", t="aa"Output""

1 ≤ m, n ≤ 105  ·  upper/lower-case English letters  ·  Follow-up: O(m + n) time.

Try it yourself

Java
class Solution {
    public String minWindow(String s, String t) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Expand right until the window is valid, then shrink left while it stays valid. A single counter missing (chars of t still uncovered) makes the validity test O(1).
PatternSliding Window

Instinct Longest, shortest or count of contiguous subarrays/substrings meeting a rule? Grow a window on the right, shrink it on the left, never step back.

Memory hack Move like a caterpillar - the head stretches forward to grab, the tail pulls up only when the body breaks the rule.

Open the Sliding Window guide →

Approaches

Brute ForceCheck Every Substring

Time O(n3 + m)Space O(1)

Count t once into need[128]. For every pair (i, j), recount s[i..j] and compare all 128 slots. Keep the shortest window that covers need.

Java
public String minWindow(String s, String t) {
    int[] need = new int[128];
    for (char c : t.toCharArray()) need[c]++;
    int bestLen = Integer.MAX_VALUE, bestStart = 0;
    for (int i = 0; i < s.length(); i++) {
        for (int j = i; j < s.length(); j++) {
            if (j - i + 1 < bestLen && covers(s, i, j, need)) {
                bestLen = j - i + 1;
                bestStart = i;
            }
        }
    }
    return bestLen == Integer.MAX_VALUE ? "" : s.substring(bestStart, bestStart + bestLen);
}

private boolean covers(String s, int i, int j, int[] need) {
    int[] have = new int[128];
    for (int k = i; k <= j; k++) have[s.charAt(k)]++;
    for (int c = 0; c < 128; c++) if (have[c] < need[c]) return false;
    return true;
}

Correct and simple, but recounting each of O(n2) windows is far too slow.

At a glance

LevelApproachTimeSpace
Brute ForceCheck Every SubstringO(n3 + m)O(1)
BetterFix Start, Grow End IncrementallyO(n2 + m)O(1)
OptimalSliding Window + Missing CounterO(n + m)O(1)
Common pitfalls
  • Tracking distinct chars only — t = "aa" needs two as.
  • Calling substring on every improvement — store start/length instead.
  • Comparing boxed Integers with == in a HashMap version (fails above 127).
Interview tips
  • Describe the template: expand until valid, shrink while valid.
  • Explain the O(1) validity check via missing instead of comparing maps.
  • Mention the “filtered s” trick when t is tiny and s huge.
Pattern
Shrinkable sliding window → shortest substring/subarray that satisfies a coverage (count) condition.
My notes saved in this browser