Skip to main content
Hard Sliding Window High frequency

Minimum Window Substring

Open on LeetCode

Approach Summary

Expand the window to include all required characters, then shrink from the left while the window remains valid. Track counts with two frequency maps.

Full Solution & Approach

This is the hardest sliding window variant because the window must contain every character of t, with the correct counts. Maintain two frequency maps: need (target counts from t) and have (counts inside the current window). Expand right until the window contains all of t — tracked with a matched counter that increments when a character reaches its required count and decrements when it falls below. Once matched === t.length, the window is valid, so record it and shrink from the left, each time removing a character and re-checking matched. Keep shrinking until the window becomes invalid, then expand right again. The running best (start index and length) is updated whenever a valid window is found. Because both pointers only move forward and each window operation is O(1) against the maps, the whole scan is O(n + m).

Right pointer advances n times and left pointer at most n times, each with O(1) map operations — O(n) time, plus O(m) to build the target counts. Two maps of at most the alphabet size give O(min(alphabet, n)) space.

Solution Code

Solution

def min_window(s: str, t: str) -> str:
    from collections import Counter
    if not t:
        return ""
    need = Counter(t)
    have = {}
    matched = 0
    left = 0
    best = (0, float('inf'))
    for right, ch in enumerate(s):
        have[ch] = have.get(ch, 0) + 1
        if ch in need and have[ch] == need[ch]:
            matched += 1
        while matched == len(need):
            if right - left + 1 < best[1] - best[0] + 1:
                best = (left, right)
            left_ch = s[left]
            if left_ch in need and have[left_ch] == need[left_ch]:
                matched -= 1
            have[left_ch] -= 1
            left += 1
    return "" if best[1] == float('inf') else s[best[0]:best[1] + 1]

Edge Cases to Watch

  • t longer than s — no window can contain it, return ""
  • t is empty — return "" per problem convention
  • Characters in t not present in s — impossible, return ""
  • Window that touches the start or end of s — the pointers naturally cover it

How to Recognize This Pattern

  • Minimum window containing all of another string

Complexity Analysis

Time Complexity

O(n + m)

Space Complexity

O(m)

Tags

String Hash Map Sliding Window

This site is free. If these guides are helping your prep, consider buying me a coffee. ☕

Support →
Buy me a coffee