Skip to content

Min Window Substring

Problem

Given strings s and t, find the minimum window substring of s that contains all characters of t (including duplicates). Return "" if no such window exists.

Approach

Variable-size sliding window with Counter for "need" and "have" tracking. Expand the right pointer to include characters, shrink the left pointer to minimize the window once all characters are satisfied.

When to Use

Minimum window containing all required elements — "smallest substring with all chars", "shortest subarray covering set". Expand right to satisfy, shrink left to minimize. Streaming log/event filtering.

Complexity

TimeO(n) where n = len(s) -- each character visited at most twice
SpaceO(k) where k = number of unique characters in t

Source

"""Minimum window substring.

Problem:
    Given strings s and t, find the minimum window substring of s
    that contains all characters of t (including duplicates).
    Return "" if no such window exists.

Approach:
    Variable-size sliding window with Counter for "need" and "have"
    tracking. Expand the right pointer to include characters, shrink
    the left pointer to minimize the window once all characters are
    satisfied.

When to use:
    Minimum window containing all required elements — "smallest substring
    with all chars", "shortest subarray covering set". Expand right to
    satisfy, shrink left to minimize. Streaming log/event filtering.

Complexity:
    Time:  O(n) where n = len(s) -- each character visited at most twice
    Space: O(k) where k = number of unique characters in t
"""

from collections import Counter


def min_window(s: str, t: str) -> str:
    """Return the minimum window in *s* that contains all chars of *t*.

    >>> min_window("ADOBECODEBANC", "ABC")
    'BANC'
    >>> min_window("a", "a")
    'a'
    >>> min_window("a", "aa")
    ''
    """
    if not t or not s:
        return ""

    need: Counter[str] = Counter(t)
    missing = len(t)
    left = start = end = 0

    for right, ch in enumerate(s, 1):  # right is 1-indexed
        if need[ch] > 0:
            missing -= 1
        need[ch] -= 1

        if missing == 0:
            # Shrink from left while window stays valid
            while need[s[left]] < 0:
                need[s[left]] += 1
                left += 1

            if not end or right - left < end - start:
                start, end = left, right

            # Invalidate window to search for smaller ones
            need[s[left]] += 1
            missing += 1
            left += 1

    return s[start:end]
This page lives in git. Anyone can propose an edit. Edit this page View source

A reading surface for the DSA study packet. Content is tracked in git; every page links to its source.