all entries
A-019Day 192026.05.21hardleetcode #76neetcode150

Minimum Window Substring

#hash-table#string#sliding-window
leetcode #76 · minimum-window-substring
01

Problem

· problem
P.019

Minimum Window Substring

leetcode #76

Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "". The testcases will be generated such that the answer is unique.

constraints
  • · 1 ≤ m, n ≤ 10^5 (lengths of s and t)
  • · s and t consist of uppercase and lowercase English letters
  • · Answer is guaranteed to be unique
// paraphrased summary — see source for full text
examples
example 1input → output
"ADOBECODEBANC"
"ABC"
BANC
example 2input → output
"a"
"a"
a
example 3input → output
"a"
"aa"
02

Pre-solve

· pre-solve
● 1list shown● 2select● 3reveal
  • What if s contains characters not in t?
  • Can the result be an empty string?
  • Must we match exact character frequencies?
  • Should we check all possible substrings?
  • Must we track all characters in s, even those not in t?
  • What if t is longer than s?
  • What does the 'have' variable represent?
check the items you would ask, then press confirm
// session-only state — refresh resets (repeatable practice)
03

Logic Structure

· logic
● 1slots shown● 2pick per slot● 3reveal
// pick one code line per slot to assemble the algorithm flow. no typing — just the logic skeleton.
step 1· Early Termination Check
if len(s) < len(t):
if len(s) == len(t): return ""
if len(t) == 0: return s
if len(s) > len(t) * 2: continue
step 2· Build Target Frequency Map
countT[c] = 1 + countT.get(c, 0)
countT = set(t)
countT[c] = 1
countT = {c: 1 for c in set(t)}
step 3· Initialize Tracking Variables
have, need = 0, len(countT)
have, need = 0, len(t)
have, need = len(countT), 0
have, need = len(s), len(t)
step 4· Expand Window and Update Countsnested
window[c] = 1 + window.get(c, 0)
window[c] = countT[c]
if c in countT: window[c] = 1 + window.get(c, 0)
window[s[r-1]] += 1
step 5· Check if Character Requirement Metnested
if c in countT and window[c] == countT[c]:
if window[c] == countT[c]: have += 1
if c in countT and window[c] >= countT[c]: have += 1
if c in countT: have += 1
step 6· Shrink Window While Validnested
while have == need:
while have < need:
while have > 0:
if have == need:
step 7· Remove Left Character and Adjust Tracking│ │ nested
window[s[l]] -= 1
window[s[l]] -= 1; l += 1
l += 1; window[s[l]] -= 1
if window[s[l]] < countT[s[l]]: have -= 1
pick one option per slot
// format: slot — recursive / DP patterns use ordering / state-first formats. ADR-08 follow-up.
04

Solve · Trace

· solve
solution.py
1
class Solution:
2
    def minWindow(self, s: str, t: str) -> str:
3
        if len(s) < len(t):
4
            return ""
5
6
        countT, window = {}, {}
7
        for c in t:
8
            countT[c] = 1 + countT.get(c, 0)
9
10
        have, need = 0, len(countT)
11
        res, resLen = [-1, -1], float("infinity")
12
        l = 0
13
        for r in range(len(s)):
14
            c = s[r]
15
            window[c] = 1 + window.get(c, 0)
16
17
            if c in countT and window[c] == countT[c]:
18
                have += 1
19
20
            while have == need:
21
                # update our result
22
                if (r - l + 1) < resLen:
23
                    res = [l, r]
24
                    resLen = r - l + 1
25
                # pop from the left of our window
26
                window[s[l]] -= 1
27
                if s[l] in countT and window[s[l]] < countT[s[l]]:
28
                    have -= 1
29
                l += 1
30
        l, r = res
31
        return s[l : r + 1] if resLen != float("infinity") else ""
mental dry-run cases
// walk each case in your head; expand the worked example below if stuck.
case 1
"ADOBECODEBANC"
"ABC"
BANC
case 2
"a"
"a"
a
case 3
"a"
"aa"
// UI does not walk-through — you do the dry-run mentally. Expand the worked example if stuck.