</> MAANG.io
coding interview ยท 101

Foundations

Master coding interviews with comprehensive coverage of data structures, algorithms, and problem-solving techniques. Progress from fundamentals to advanced topics with expertly curated content.

0/255 solved 0% complete

The Substring-Matching Template

What is this?

Think of the window as a spotlight that can both widen and narrow. You first stretch its right edge outward until it covers everything you need, then squeeze its left edge inward to trim away anything wasteful โ€” keeping the best window you have seen along the way. This one breathing motion, expand then contract, solves a surprising number of "find the smallest or longest stretch" problems with the same short piece of code.

flowchart TD A["Start with an empty window"] --> B["Expand the right edge until valid"] B --> C["Shrink the left edge while still valid"] C --> D["Record the best window seen"] D --> B

๐Ÿ’ก Fun fact: This expand-then-contract template is the same shape behind real-time search-and-highlight features and DNA motif scanners in bioinformatics, which hunt for the shortest stretch of a genome containing a given set of markers.

๐Ÿ”“ The 2 problems in this chapter are free. Sign in with Google or Microsoft to start solving.


Core idea: Almost every hard sliding-window problem fits one template: grow the window on the right until it satisfies a condition, then shrink it from the left while it stays satisfied, recording the best as you go. Learn this ~10-line shape once and Minimum Window Substring, Longest Substring Without Repeating, and their cousins all become fill-in-the-blanks.


The template

need = Counter(t)          # what the window must contain (problem-specific)
have, required = 0, len(need)
left = 0
for right, ch in enumerate(s):
    # 1) include s[right] in the window state
    if ch in need:
        need[ch] -= 1
        if need[ch] == 0: have += 1
    # 2) while the window is VALID, try to shrink and record the answer
    while have == required:
        update_answer(left, right)
        lch = s[left]
        if lch in need:
            if need[lch] == 0: have -= 1
            need[lch] += 1
        left += 1

Only three things change per problem: what state the window tracks, what "valid" means, and whether you record on growth (longest) or on shrink (shortest).


The problems

Expand-to-valid, contract-to-optimal branches into Minimum Window Substring (smallest covering t) and Longest Substring Without Repeating (no duplicates)

  • Minimum Window Substring โ€” the template at full strength: a need/have counter finds the smallest window containing all of t.
  • Longest Substring Without Repeating Characters โ€” the validity is "no duplicate"; the last-seen-index trick jumps the left edge in O(1).

Key takeaways

  • One template: expand right to validity, contract left to optimality, record as you go.
  • Customize three things: the window state, the validity test, and record-on-grow vs record-on-shrink.
  • A required/formed counter makes validity O(1).
  • Last-seen-index lets "no repeats" jump the left edge instead of stepping.
  • Why interviewers love it: recognizing that a new problem is this template is the senior move.

Start here: Minimum Window Substring (the full template), then Longest Substring Without Repeating Characters.

Longest Substring Without Repeating Characters

Core idea: Walk a window across the string and grow it on the right as long as every character inside stays unique. The moment the new character is one you've already seen inside the current window, jump the left edge forward to just past that duplicate's previous position โ€” then keep growing. Track the widest the window ever got.

Problem, rephrased

Imagine you're reading a stream of keystrokes one character at a time, and you want the longest unbroken run you could highlight in which no character repeats. As you scan left to right, you keep a highlight (a window) over a stretch of text. Every new character either extends the highlight โ€” if it's fresh โ€” or forces you to drop characters off the left end until the repeat is gone, then continue.

You are not allowed to skip characters: the answer must be a contiguous substring, not a scattered subsequence. "pwke" reads the right letters but skips the middle w โ€” that's a subsequence, and it doesn't count. "wke" is contiguous, and it does.

Formally: given a string s, return the length of the longest substring of s in which all characters are distinct.

Input Output A longest window Why
"abcabcbb" 3 "abc" the second a repeats, capping the run at 3
"bbbbb" 1 "b" every character is the same
"pwwkew" 3 "wke" "wke" beats "pw" (2) and "kew" (3)
"" 0 "" nothing to highlight

Sign in to continue reading

The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.

Sign in to read the full lesson

Sign in to MAANG.io

Use your Google or Microsoft account โ€” no password to remember.

Continue with Google Continue with Microsoft

Please accept the terms above to continue.