001 Notes

State Space Exploration Superset Professional Playbook

Overview and Reading Path

Use this guide when a problem can be solved by recursive calls, graph/grid movement, choices, memoization, BFS, tree traversal, string positions, or range splitting, and you need to decide what the call really means.

Read in this order:

  1. Learn the superset family map.
  2. Learn the five universal questions.
  3. Learn the state-versus-unit vocabulary bridge.
  4. Learn the forward-work versus upward-work distinction.
  5. Translate the problem with the unified workflow.
  6. Pick the execution family.
  7. Use the merged translation table for pattern recognition.
  8. Study the canonical examples.
  9. Study the dry runs.
  10. Use the decision rules, failure modes, performance notes, and cheat sheets.

This guide intentionally repeats the same questions from several angles. That is useful because most mistakes come from choosing the engine too early.

Do not start with:

This is recursion.
This is DP.
This is graph.
This is string.

Start with:

What does one call/state/unit know?
What can it legally do next?
What must it return?

Core Vocabulary

TermMeaning
StateThe minimum facts needed to continue correctly
UnitA range, subtree, token interval, or segment owned by one recombine call
ChoiceA legal action available from a state
SplitA divide/recombine choice that creates child units
TransitionThe move from one state to another
Base caseThe smallest unit or terminal state solved directly
Stop conditionA rule that records, rejects, returns, or finishes
PathThe concrete construction built by backtracking
TrackerFast legality memory such as used values, occupied columns, or visited cells
Memo keyThe state fields that determine a repeated future answer
FrontierThe queue/layer of states currently ready to process
SummaryThe compact answer returned by a child call
Cross workWork needed between child units, such as cross inversions or crossing subarray
RecombineBuilding a parent answer from child summaries
String stateIndex, pair, path, center, interval, trie node, automaton node, or window

Beginner Mental Model

A problem is a world. A state is one place in that world. A move takes you to another place. A stop condition says when a path is done. An answer type says what comes back.

I am here.
I know these facts.
These moves are legal.
This move changes the state.
When I stop, I return or record this kind of answer.

Visual:

The beginner question is always:

    What is the world?
    Where am I standing?
    Where can I move next?
    What do I remember?
    What happens when I stop?

1) Matrix / grid world

problem: explore land cells, find a path, count a region, search a word

        c0   c1   c2   c3
      +----+----+----+----+
r0    | .  | #  | .  | .  |
      +----+----+----+----+
r1    | .  | S  | .  | .  |
      +----+----+----+----+
r2    | .  | .  | #  | .  |
      +----+----+----+----+

state = current cell = (r1, c1)

possible next states:

                (r0,c1) blocked
                       ^
                       |
        (r1,c0) <--- (r1,c1) ---> (r1,c2)
                       |
                       v
                    (r2,c1)

memory can be:
visited cells, current path, distance layer, remaining keys, current word index

classification:
mark and move only          -> pure explorer / flood fill
need shortest path          -> BFS explorer
need choose letters in path -> backtracking explorer
same cell plus extra facts  -> richer state, such as (r,c,keys) or (r,c,wordIndex)

2) Tree world

problem: traverse, compute depth, find diameter, collect paths

                   A
                /  |  \
               B   C   D
             /   \
            E     F

state = current node = B

possible next states:

              parent A
                 ^
                 |
                 B
               /   \
              E     F

If the tree is rooted and you only move downward:

    B -> E
    B -> F

If the problem treats the tree like an undirected graph:

    B -> A
    B -> E
    B -> F

classification:
visit nodes and mark/collect       -> traversal explorer
return height/count/best upward    -> tree summary recursion
split left/right and rebuild value -> divide/recombine style

3) String index world

problem: decode, segment, match, partition, scan

string:

    s = "leetcode"
         0 1 2 3 4 5 6 7 8
         l e e t c o d e
         ^
       state i=0

possible next states in Word Break:

    i=0
     |
     | take "leet"
     v
    i=4
     |
     | take "code"
     v
    i=8 stop

state = index i
move = choose a valid word/piece starting at i
stop = i == len(s)
memory = memo[i] if the same index repeats

classification:
single pass with reusable border/hash -> string structure
choose substrings and undo            -> backtracking
same index repeats                    -> DP explorer

4) Choice / path world

problem: subsets, permutations, partitions, N-Queens

nums = [2, 7, 9]

state = (index, current_path)

                         (i=0, path=[])
                         /             \
                    skip 2             take 2
                       /                 \
              (i=1, [])              (i=1, [2])
              /       \              /          \
         skip 7      take 7     skip 7        take 7
           |            |          |              |
       (i=2, [])    (i=2,[7])  (i=2,[2])   (i=2,[2,7])

move = choose one legal branch
undo = remove the choice before trying the next branch
stop = index == len(nums)
answer = record the current path, or count valid paths

classification:
concrete path/output matters -> choice explorer / backtracking
only best count/value matters -> often DP after compressing the state

5) Two-index DP world

problem: LCS, edit distance, interleaving string, distinct subsequences

state = one cell in an index grid = (i, j)

        text2 index j
           0     1     2
        +-----+-----+-----+
 i=0    |0,0  |0,1  |0,2  |
        +-----+-----+-----+
 i=1    |1,0  |1,1  |1,2  |
        +-----+-----+-----+
 i=2    |2,0  |2,1  |2,2  |
        +-----+-----+-----+
             ^
             |
        current state could be (2,1)

possible next states depend on the recurrence:

    LCS:
        if chars match:    (i,j) -> (i+1,j+1)
        if chars differ:   (i,j) -> (i+1,j) and (i,j+1)

    Edit distance:
        insert:            (i,j) -> (i,j+1)
        delete:            (i,j) -> (i+1,j)
        replace/match:     (i,j) -> (i+1,j+1)

memory = dp[i][j]
stop = one index reaches the end
answer = value returned for this pair of suffixes/prefixes

classification:
same (i,j) repeats and returns a value -> DP explorer
moving through characters is the world -> string state explorer

The shared picture:

    problem world -> current state -> legal next states -> stop/return

What changes between families is what "return" means:

pure explorer:      mark and move
choice explorer:    record a completed path
DP explorer:        return cached answer for this state
BFS explorer:       return shortest layer distance
string explorer:    move through index/pair/path/match state
recombine:          return child summary to parent

For divide/recombine, the wording changes:

I own this unit.
This is the smallest direct answer.
I split into these child units.
Each child returns this summary.
I combine summaries into my own summary.

Same recursion. Different emphasis.

Superset Family Map

State Space Exploration Superset
|
|-- Pure Explorer
|   |-- flood fill
|   |-- graph component traversal
|   |-- simple tree traversal
|   |-- reachability marking
|
|-- Choice Explorer
|   |-- subsets
|   |-- permutations
|   |-- combinations
|   |-- partitioning
|   |-- generated valid objects
|
|-- Constraint Explorer
|   |-- N-Queens
|   |-- Sudoku
|   |-- matchsticks to square
|   |-- k equal subset partitioning
|
|-- DP Explorer
|   |-- index DP
|   |-- capacity DP
|   |-- amount DP
|   |-- two-string DP
|   |-- interval DP
|   |-- bitmask DP
|
|-- BFS Explorer
|   |-- shortest equal-cost moves
|   |-- multi-source time layers
|   |-- state with extra carried facts
|
|-- String State Explorer
|   |-- index state
|   |-- pair state
|   |-- path state
|   |-- center/radius state
|   |-- interval state
|   |-- trie node state
|   |-- automaton state
|   |-- rolling window state
|
|-- Tree Summary Bridge
|   |-- maximum depth
|   |-- diameter
|   |-- LCA
|   |-- validate BST with carried bounds
|
`-- Divide/Recombine Special Case
    |-- merge sort
    |-- count inversions
    |-- maximum subarray by summaries
    |-- tree construction
    |-- serialization and deserialization
    |-- segment tree
    |-- recursive parsing

High-Level Comparison

FamilyMain questionMain state/unitMain return shapeTypical engine
Pure explorerWhat can I reach?node, cell, frontier itemmark, count, booleanDFS/BFS traversal
Choice explorerWhat can I build?index plus pathrecorded constructionsbacktracking
Constraint explorerWhich choices stay legal?variable plus trackersvalid construction or decisionpruned backtracking
DP explorerDoes this future repeat?memo keycount, boolean, min, maxmemo/table
BFS explorerWhat is shortest with equal-cost moves?queue statedistanceBFS layers
String state explorerWhere am I in the string relation?index, pair, center, trie node, automatoncount, best, match, decisionDP, backtracking, automaton, hashing
Tree summary bridgeWhat should child calls return upward?node plus carried factssimple summary or flagstree DFS
Divide/recombineWhat child summaries rebuild the parent?range, subtree, token range, segmentsame-type summarysplit/solve/combine

Core Mental Model

Every problem in this superset can be described with five questions.

1. Where am I?
2. What information am I carrying?
3. What moves, choices, or splits are legal now?
4. Where does each move lead?
5. What do I record, return, or combine when this call finishes?

If those questions are clear, code is usually mechanical. If those questions are vague, code usually becomes a mixture of guesses.

Universal recursive exploration:

solve(state):
    if terminal(state):
        return answer_from(state)

    result = neutral_value
    for move in legal_moves(state):
        next_state = transition(state, move)
        child_answer = solve(next_state)
        result = combine(result, child_answer)

    return result

Universal pure traversal:

visit(state):
    if invalid(state) or seen(state):
        return

    mark(state)
    for next_state in neighbors(state):
        visit(next_state)

Universal backtracking:

search(state, path):
    if complete(state):
        record copy(path)
        return

    for choice in legal_choices(state):
        apply choice
        search(next_state, path)
        undo choice

Universal DP:

answer(state):
    if base case:
        return base value
    if state in memo:
        return memo[state]

    memo[state] = combine answers from next states
    return memo[state]

Universal BFS:

queue = [start_state]
seen = {start_state}

while queue:
    state, distance = pop_front(queue)
    if target(state):
        return distance
    for next_state in legal_neighbors(state):
        if next_state not in seen:
            seen.add(next_state)
            push(next_state, distance + 1)

Universal divide/recombine:

solve(unit):
    if unit is base case:
        return base summary

    child_units = split(unit)
    child_summaries = [solve(child) for child in child_units]
    cross_summary = compute_cross_work_if_needed(child_summaries)
    return combine(child_summaries, cross_summary)

State vs Unit Translation Wall

The state-space wording and divide/recombine wording are two views of the same recursive skeleton.

State Space wordDivide/Recombine wordIntuition
stateunitthe call owns a configuration or a range-like piece
choicesplitthe call decides a move or divides into child pieces
transitionchild callthe call advances or delegates to smaller pieces
stop conditionbase casethe call knows when direct answer is possible
answer from statechild summarythe child returns what the parent needs
combine child answersrecombinethe parent rebuilds its own answer
visited/memosummary/index/cacheremembered information prevents repeated work

Visual:

State exploration:

state A --move--> state B --move--> state C
   |                 |                 |
 mark/record/cache  mark/cache        stop

Divide/recombine:

               parent summary
              /              \
     left child summary    right child summary
          /                      \
      base unit                base unit

Moving Forward vs Rebuilding Upward

This is the most useful boundary.

If the main work happens while moving forward, use exploration.
If the main work happens when child answers return, use recombine.

Forward work:

flood_fill(cell):
    mark cell
    move to neighbors

Upward work:

count_inversions(range):
    solve left half
    solve right half
    count cross pairs while merging
    return sorted range and count

Middle work:

diameter(node):
    ask children for height
    update best path through current node
    return height

Diameter is not pure marking. It is also not the same as full merge counting. It is a tree summary bridge.

How To Translate Any Problem

Translate in this order.

Step 1: Identify The Goal

Ask:

What must I return?

Common answer types:

GoalUsually means
all objectsbacktracking
one valid objectsearch with early stop
countDP or combinational backtracking
minimum/maximumDP, BFS, or ordered optimization
shortest equal-cost movesBFS
reachability/componentspure traversal
rebuilt structuredivide/recombine
string match positionsstring traversal or automaton

Step 2: Decide What One Call Owns

A call may own:

index
path
row, col
node
node plus bounds
amount
capacity
i, j
left, right
mask
trie_node
automaton_state
range [lo, hi]
token interval
segment-tree interval

The owned object determines the rest.

Step 3: Remove What Does Not Belong

State should be complete but minimal.

Complete:

contains every fact that changes future choices or answers

Minimal:

does not include facts already derivable from the state

Wrong DP key:

(index, remaining, path)

Right DP key:

(index, remaining)

because the best future does not depend on the concrete path.

Step 4: Find Moves, Choices, Or Splits

Move examples:

grid:
    up, down, left, right

lock:
    rotate one wheel up or down

string index:
    consume one character, two digits, or one dictionary word

two-string DP:
    match both, skip first, skip second, edit

tree:
    visit left child, visit right child

divide/recombine:
    split range, split traversal arrays, split at operator

Step 5: Find Stop Or Base Cases

Stop examples:

index == n
remaining == 0
node is None
out of bounds
visited already
target reached
range is empty
range has one item
token is a number

Write stops before writing recursive calls.

Step 6: Define Return Shape

Return shape decides the family.

Return shapeFamily
nothing, mark onlypure explorer
completed pathbacktracking
count / boolean / min / max from stateDP explorer
distanceBFS explorer
child height / flagstree summary bridge
sorted half / segment aggregate / subtree rootdivide/recombine
border, hash, trie node, automaton statestring structure

Step 7: Choose Engine

Use this quick guide:

Need all valid paths or constructions?
    -> backtracking

Need to mark reachable nodes/cells?
    -> pure DFS/BFS traversal

Need shortest equal-cost path?
    -> BFS

Can the same state repeat?
    -> DP

Does a small set belong in the state?
    -> bitmask

Does parent need child summaries?
    -> tree summary or divide/recombine

Does string progress or mismatch memory dominate?
    -> string state / string structure

Pure Explorer / Tail-Recursion-Like Traversal

Pure explorers mostly move and mark.

Use when:

  • the goal is reachability
  • the goal is connected component marking
  • each state is processed once
  • child calls do not return rich summaries
  • traversal side effects are enough

Examples:

Number of Islands
Flood Fill
Max Area of Island
Clone Graph
Pacific Atlantic Water Flow
simple tree preorder/inorder/postorder traversal

Tail-recursion-like intuition:

dfs(cell):
    mark cell
    continue to neighbors

This feels tail-recursive because the call mostly pushes exploration forward. But multi-neighbor DFS is not strict compiler tail recursion. The practical point is:

No sibling result needs a rich recombine step.

Pure explorer checklist:

What is the current node/cell?
What makes it invalid?
What marks it as processed?
What neighbors are legal?
Can I process each state once?
What does the traversal leave behind?

Choice Explorer

Choice explorers build concrete objects.

Use when:

  • the output asks for all combinations, permutations, partitions, boards, or paths
  • a partial answer is being built
  • choices must be tried one by one
  • sibling branches must not share mutations

Core idea:

choose
recurse
undo

Examples:

Subsets
Permutations
Combination Sum
Generate Parentheses
Restore IP Addresses
Palindrome Partitioning
Word Search

Backtracking skeleton:

path = []

search(state):
    if complete:
        answers.add(copy(path))
        return

    for choice in legal_choices(state):
        apply choice
        search(next_state)
        undo choice

The important rule:

Only copy the path when recording an answer.

Constraint Explorer

Constraint explorers are choice explorers with fast legality memory.

Use when:

  • many choices are illegal
  • legality is based on repeated facts
  • checking the whole board/path every time is too slow

Examples:

N-Queens:
    columns
    row - col diagonals
    row + col diagonals

Sudoku:
    row digit masks
    column digit masks
    box digit masks

Permutations with duplicates:
    used indexes
    duplicate sibling skip rule

Constraint skeleton:

choose next variable
for candidate in candidates:
    if candidate violates tracker:
        continue
    apply candidate
    update tracker
    search(next state)
    restore tracker
    undo candidate

The undo should mirror the mutation order.

Bitmask State

A bitmask stores a small set inside an integer.

Use when:

  • the number of items is small
  • each item has a stable index
  • you need cheap copy, membership, hashing, or visited keys

Examples:

used indexes in permutations
visited nodes in shortest path visiting all nodes
collected keys in a grid
selected skills in smallest sufficient team
available digits in Sudoku

Operations:

bit = 1 << i

contains i:
    mask & bit

add i:
    mask | bit

remove i:
    mask & ~bit

all n items:
    mask == (1 << n) - 1

Visual:

items: A B C D
index: 0 1 2 3
mask:  1 0 1 0

set = {A, C}

Bitmask is not an algorithm family by itself. It is a representation used by backtracking, DP, and BFS.

DP Explorer

DP explorers ask:

What is the answer from this state?

Use when:

  • the same state can be reached more than once
  • the answer from that state is deterministic
  • the output is count, boolean, minimum, maximum, or score

Top-down DP:

write recursive answer(state)
memoize by the full state key
reuse answer when state repeats

Bottom-up DP:

choose an order where dependencies are already known
fill a table
return target cell

Top-down template:

from functools import lru_cache

def solve_problem(data):
    @lru_cache(None)
    def solve(state):
        if base_case(state):
            return base_value
        ans = neutral_value
        for next_state in next_states(state):
            ans = combine(ans, solve(next_state))
        return ans

    return solve(start_state)

Key rule:

The memo key must include every variable that changes the future answer.

BFS Explorer

BFS explorers ask:

What is the shortest equal-cost path to a target state?

Use when:

  • every move has the same cost
  • target can be recognized
  • shortest number of moves is required
  • state space is bounded or can be pruned

Examples:

Open the Lock
Word Ladder
Minimum Genetic Mutation
Sliding Puzzle
Rotting Oranges
Shortest Path Visiting All Nodes
Shortest Path in Grid With Obstacles Elimination

Visited timing:

mark visited when pushing into the queue

Why:

the first time a state is pushed, it has already been reached by the shortest layer

If edge costs differ, use weighted shortest-path logic instead of plain BFS.

String State Explorer

String problems are still state exploration when the main question is:

Where am I in the string relation, and what character/index move is legal?

State shapes:

ShapeMeaningExamples
indexposition in one stringDecode Ways, Word Break, Restore IP
(i, j)positions in two stringsLCS, Edit Distance, Distinct Subsequences
(row, col, k)grid path plus word indexWord Search
(trie_node, index/path)dictionary prefix stateWord Search II, Trie search
(center, radius)palindrome expansionLongest Palindromic Substring
(l, r)intervalLongest Palindromic Subsequence, parsing
automaton statereusable match progressKMP, Aho-Corasick
fixed windowcurrent substringRepeated DNA, rolling hash

String state cards:

Decode Ways:
    state = index
    move = decode one or two valid digits
    stop = index == len(s)
    return = number of ways
    shape = string-index DP

Word Break:
    state = index
    move = consume one dictionary word
    stop = index == len(s)
    return = possible/count
    shape = string-index DP

Restore IP Addresses:
    state = index, parts, path
    move = choose next valid segment
    stop = consumed string and built four parts
    return = completed addresses
    shape = string choice explorer

Palindrome Partitioning:
    state = index, path
    move = choose palindromic prefix
    stop = index == len(s)
    return = completed partitions
    shape = string choice explorer

Word Search:
    state = row, col, word_index, visited cells
    move = move to matching neighbor
    stop = word complete or invalid path
    return = found/not found
    shape = path explorer with undo

Word Search II:
    state = row, col, trie_node, visited cells
    move = follow trie edge through neighboring cell
    stop = terminal word or dead prefix
    return = found words
    shape = path explorer plus trie memory

LCS:
    state = (i, j)
    move = match both or advance one string
    stop = one string exhausted
    return = best length
    shape = two-string DP

Edit Distance:
    state = (i, j)
    move = match, insert, delete, replace
    stop = one string exhausted
    return = minimum edits
    shape = two-string DP

KMP:
    state = text index, pattern index
    move = match forward or fallback by border table
    stop = pattern matched or text exhausted
    return = match positions
    shape = automaton-like traversal

String rule:

Classify the string state shape before naming the algorithm.

Tree Summary Bridge

Tree problems often sit between pure traversal and recombine.

Simple traversal:

preorder(node):
    visit node
    preorder(left)
    preorder(right)

Simple returned summary:

height(node):
    return 1 + max(height(left), height(right))

Bridge summary:

diameter(node):
    left_height = height(left)
    right_height = height(right)
    best = max(best, left_height + right_height)
    return 1 + max(left_height, right_height)

True divide/recombine:

build_tree(pre_range, in_range):
    root = preorder first
    split inorder around root
    root.left = build(left ranges)
    root.right = build(right ranges)
    return root

Boundary:

Traversal:
    moving through existing structure

Tree summary:
    moving through existing structure and returning small facts

Tree construction:
    rebuilding a new structure from split evidence

Divide/Recombine Special Case

Use divide/recombine when:

  • one call owns a unit
  • the unit can be split
  • children return summaries
  • parent needs those summaries
  • cross-boundary work may be necessary
  • parent returns the same kind of summary upward

Core questions:

What is the unit?
What is the base case?
How does it split?
What does each child return?
What cross-boundary work exists?
How does the parent combine?
Does the parent return the same summary type?

Examples:

Maximum Subarray:
    summary = total sum, best prefix, best suffix, best subarray
    cross = left suffix + right prefix

Count Inversions:
    summary = sorted values plus count
    cross = left values greater than right values

Build Tree:
    summary = subtree root
    split = root position in inorder traversal

Segment Tree:
    summary = interval aggregate
    split = midpoint

Recursive Parsing:
    summary = possible values or parsed node
    split = operator or grammar boundary

Unified Translation Table

ProblemLensState / unitMove / choice / splitStop / base caseReturn / memory / combineExecution shapeWhy this classification
SubsetsChoice explorerindex, pathtake or skipindex == nrecord pathbacktrackingconcrete construction paths are output
Subsets IIChoice explorerindex, path, duplicate ruletake or skip unique choiceindex == nrecord pathduplicate-pruned backtrackingsibling duplicate choices must be skipped
PermutationsChoice explorerpath, usedchoose unused itemlen(path) == nrecord pathbacktrackingorder of chosen items matters
Generate ParenthesesConstraint exploreropened, closed, pathadd open or legal closefull lengthrecord pathconstraint backtrackinglegality constraints define choices
Combination SumChoice explorerstart, remaining, pathpick candidateremaining == 0record pathbacktrackingchoices build combinations
Restore IP AddressesString choice explorerindex, parts, pathchoose next segmentconsumed string and four partsrecord addressbacktrackingstring index advances by segment
Palindrome PartitioningString choice explorerindex, pathchoose palindromic prefixindex == nrecord partitionbacktrackingeach move consumes one valid substring
Word SearchString path explorerrow, col, word_index, visited cellsmove to matching neighborword complete or invalidbooleanDFS backtrackinggrid path plus word index is state
Maximum Depth of Binary TreeTree traversalnodevisit childrennode is Noneheighttree DFSsimple returned summary
Diameter of Binary TreeTree summary bridgenodeask child heightsnode is Noneheight plus global/bundled besttree DFS summarychild summaries combine through current node
Validate BSTTree traversal with carried constraintsnode, low, highvalidate children with tighter boundsnull or invalidbooleantree DFScarried bounds are state
Lowest Common AncestorTree traversal with return flagsnodesearch left and righttarget or nullnode/flagstree DFSchild returns determine ancestor
Clone GraphPure exploreroriginal node, clone mapvisit neighborsalready clonedclone referenceDFS/BFS with mapclone map is visited memory
Number of IslandsPure explorerrow, colvisit adjacent landboundary/water/visitedmark componentflood fillmoving and marking is the main work
Max Area of IslandPure explorer with countrow, colvisit adjacent landboundary/water/visitedcountflood fillcount is simple accumulation
Pacific Atlantic Water FlowPure multi-source explorerrow, col, ocean sidereverse-flow neighborsno new cellsreachable setsDFS/BFSreachability is the goal
Course ScheduleFrontier explorerzero-indegree frontierprocess available courseall processed or stuckvaliditytopological BFSfrontier models released states
Is Graph BipartitePure explorer with labelsnode, color mapcolor neighborsconflict or donevalidityDFS/BFS coloringlabels prove structure consistency
N-QueensConstraint explorerrow, board, trackersplace safe queenrow == nboardconstraint backtrackingtrackers make legality fast
SudokuConstraint explorerboard, empty cell, trackerslegal digitboard filledsolved boardconstraint searchchoice legality dominates
Matchsticks to SquareConstraint explorerindex, side lengthsplace stick on a sideall sticks placedbooleanbacktrackingside lengths are carried state
Partition to K Equal Sum SubsetsChoice + bitmaskmask, bucket_sum, buckets_doneadd unused numberall buckets filledbooleanbitmask backtrackingmask represents chosen set
House RobberDP explorerindexrob or skippast endbest valueDPsuffix answer repeats
House Robber IIDP explorerindex, linear caserob or skiprange exhaustedbest valueDP over casescircle becomes two ranges
0/1 KnapsackDP explorerindex, capacitytake or skipno itemsbest valueDPrepeated item/capacity states
Target SumDP explorerindex, sumadd or subtractno numberscountDP/backtrackingrepeated sums can be cached
Coin Change MinimumDP exploreramountchoose coinamount zerominimum coinsDPamount states repeat
Coin Change CountDP explorercoin index, remaininguse or skip coinremaining zerocountDPstate controls combination order
Decode WaysString index DPindexconsume one/two digitsend of stringcountDPsuffix answer depends on index
Word BreakString index DPindexconsume dictionary wordend of stringboolean/countmemo DFS/DPsuffix answer repeats
Longest Common SubsequenceTwo-string DPi, jmatch or advanceone string exhaustedbest lengthDPsuffix pair determines answer
Edit DistanceTwo-string DPi, jinsert/delete/replace/matchone string exhaustedminimum editsDPalignment state repeats
Distinct SubsequencesTwo-string DP countingi, jskip source or match targettarget consumed/source exhaustedcountDPcounts paths through alignment states
Interleaving StringTwo-string DPi, jtake char from first/secondtarget consumedbooleanDPtarget index is derived
Unique Paths With ObstaclesGrid DP explorerrow, colmove right or downdestination reached or blockedcountDPpaths to cells overlap
Longest Increasing Path in MatrixGrid DP explorerrow, colmove to larger neighborno larger neighborlongest lengthDFS plus memoeach cell’s best future repeats
Longest Palindromic SubsequenceInterval DPl, rmatch ends or shrinkempty/singlebest lengthDPinterval answer repeats
Longest Palindromic SubstringCenter traversalcenter, radiusexpand mirrorsmismatch/boundarybest intervalpalindrome traversalmoves outward from center
Palindromic SubstringsCenter traversalcenter, radiusexpand mirrorsmismatch/boundarycountpalindrome traversalevery center explores valid radii
Word LadderString BFSwordmutate one charactertarget worddistanceBFSequal-cost word moves
Minimum Genetic MutationString BFSgenemutate one charactertarget genedistanceBFSequal-cost mutations
Open the LockBFS explorercoderotate wheeltarget codedistanceBFSequal-cost transitions
Sliding PuzzleBFS explorerboard encodingswap blanktarget boarddistanceBFSboard is compact state
Rotting OrangesMulti-source BFSrotten cells by minuterot neighborno fresh orangesminutesBFS layerslayers model time
Shortest Path in Grid With Obstacles EliminationBFS with carried staterow, col, breaksmove to neighbordestinationdistanceBFSbreaks change future reachability
All Keys GridBFS + bitmaskrow, col, key maskmove/collect keyall keysdistanceBFS bitmaskkey set belongs in visited state
Shortest Path Visiting All NodesBFS + bitmasknode, visited maskmove to neighborall visiteddistanceBFS bitmaskvisited set changes state
Smallest Sufficient TeamBitmask DPperson index, skills masktake or skip personall skillsminimum teamDPskills mask summarizes coverage
Maximum Score After N OperationsBitmask DPused mask, operationpair unused numbersall pairedmaximum scoreDPused set determines future
Maximum Subarray Divide-ConquerDivide/recombinearray rangesplit halvesone itemfour-value summarydivide and conquercrossing answer needs summaries
Merge SortDivide/recombinearray rangesplit halvesone itemsorted rangedivide and conquerchild sorted lists merge upward
Count InversionsDivide/recombinesorted rangesplit halvesone itemsorted values plus countmerge countingcross pairs require sorted children
Reverse PairsDivide/recombinesorted rangesplit halvesone itemsorted values plus countmerge countingcross pair count is upward work
Count of Smaller After SelfDivide/recombineindex rangesplit halvesone itemsorted indexes and countsmerge countingright-smaller counts happen at merge
Kth Largest ElementOrdered selectionpartition rangepivot partitionpivot rank targetselected valuequickselectpartition discards one side
Median of Unsorted ArrayOrdered selectionpartition rangepivot partitionmiddle rank foundselected valuequickselectsame partition logic selects median rank
Build Tree From Preorder/InorderDivide/recombinetraversal rangesroot splits inorderempty rangesubtree roottree constructionchildren return rebuilt subtrees
Build Tree From Inorder/PostorderDivide/recombinetraversal rangesroot splits inorderempty rangesubtree roottree constructionpostorder root defines the split and child ranges
Serialize Binary TreeRecursive codecnodeencode node/childrennulltoken streamrecursive encodingstructure flows through recursive order
Deserialize Binary TreeRecursive codectoken stream indexconsume root/childrennull tokensubtree rootrecursive decodingchild calls rebuild structure
Range Sum Query MutableRange recombineinterval nodesplit by midpointexact coveraggregatesegment treequery combines covered nodes
Range Minimum QueryRange recombineinterval nodesplit by midpointexact coveraggregatesegment treesame summary type flows upward
Different Ways to Add ParenthesesString interval recombinetoken intervalsplit at operatornumber tokenall valuesrecursive parsingoperator combines child values
Basic CalculatorGrammar recombineexpression unitparse grammar piecesatomic tokenvaluerecursive parsinggrammar defines split and combine
Decode StringGrammar recombinebracketed rangeparse child rangesliteral/closing bracketexpanded stringrecursive parsingchild expansions concatenate/repeat
Find First OccurrenceString automatontext index, pattern indexmatch or fallbackfull pattern/text endmatch indexKMPborder memory avoids restart
Repeated Substring PatternString structureprefix/suffix bordercompute borderpattern processedrepeated-unit decisionKMPborder defines reusable period
Shortest PalindromeString structureprefix palindrome borderKMP over combined stringscan completeprefix lengthKMPborder finds longest palindromic prefix
Sum of Scores of Built StringsString structureprefix match lengthreuse Z-boxscan completescore sumZ algorithmZ-box stores prefix matches
Repeated DNA SequencesString windowfixed windowslide one charall windows scannedrepeated windowsrolling hashwindow state moves forward
Longest Duplicate SubstringString + ordered searchlength and windowbinary search length, hash windowslength boundaryduplicate substringrolling hashlength order plus hash memory
Implement TrieString structuretrie nodefollow/create edgeword consumedprefix path memorytriepath represents prefix state
Word Search IIString path + triegrid cell and trie nodefollow trie edge in gridterminal/dead prefixfound wordstrie backtrackinggrid path and prefix memory combine
Aho-Corasick SearchAutomaton traversalautomaton nodeconsume char/failure linktext exhaustedemitted matchesmulti-pattern automatonnode stores reusable prefix state
Suffix Array SearchString structuresuffix rank/rangecompare suffixessearch completematch/rangesuffix indexingsorted suffix order is memory

Canonical Examples

Example: Subsets

State:

index, path

Choices:

skip nums[index]
take nums[index]

Stop:

index == len(nums)

Answer:

record copy(path)

Why:

The path itself is the output, so this is choice exploration.

Example: N-Queens

State:

row, path, occupied_columns, occupied_diag1, occupied_diag2

Choices:

place queen in any safe column of current row

Trackers:

column
row - col diagonal
row + col diagonal

Why:

The board is built by choices, but fast legality trackers make the search practical.

Example: House Robber

State:

index

Recurrence:

best(index) = max(best(index + 1), nums[index] + best(index + 2))

Why:

Once index is known, the best future is fixed.

Example: Word Break

State:

index

Moves:

consume any dictionary word that starts at index

Why:

This is string-index DP, not substring brute force.

Example: LCS

State:

i, j

Moves:

if a[i] == b[j]:
    move to i + 1, j + 1
else:
    move to i + 1, j
    move to i, j + 1

Why:

The suffix pair determines the answer.

Example: Number of Islands

State:

row, col

Move:

move to adjacent land cell

Why:

This is pure exploration. Marking reachable land is the work.

Example: Diameter of Binary Tree

State:

node

Return:

height of subtree

Side update:

best diameter through current node

Why:

This is a tree summary bridge. Child heights are recombined through the node.

Example: Build Tree From Traversals

Unit:

preorder range, inorder range

Split:

root value splits inorder range into left and right subtree ranges

Return:

subtree root

Why:

This is true divide/recombine because child calls rebuild child subtrees.

Example: Count Inversions

Unit:

array range

Child summary:

sorted values plus inversion count

Cross work:

count left values greater than right values during merge

Why:

The sorted child summaries are necessary for the parent answer.

State:

text index, pattern index

Memory:

border table

Move:

match advances both indexes
mismatch follows fallback border

Why:

This is automaton-like string traversal with reusable mismatch memory.

Dry Runs

Dry Run: Flood Fill As Pure Explorer

Grid:

1 1 0
1 0 1
0 1 1

Start:

(0, 0)

Trace:

visit (0,0)
    mark it
    move to (0,1)
        mark it
    move to (1,0)
        mark it

Invariant:

every marked cell belongs to the current component

Verdict:

pure explorer

No child returns a rich summary to combine.

Dry Run: Word Search With Undo

Board:

A B C
D E F

Word:

ABE

Trace:

A matches index 0
mark A
move to B

B matches index 1
mark B
move to E

E matches index 2
word complete

Undo:

when a branch fails:
    unmark the cell before trying the next neighbor

Invariant:

visited cells are exactly the current word-prefix path

Verdict:

path explorer with undo

Dry Run: Subsets

Input:

[1, 2]

Tree:

dfs(0), path=[]
|-- skip 1
|   `-- dfs(1), path=[]
|       |-- skip 2 -> []
|       `-- take 2 -> [2]
`-- take 1
    `-- dfs(1), path=[1]
        |-- skip 2 -> [1]
        `-- take 2 -> [1, 2]

Verdict:

choice explorer

Dry Run: Word Break

String:

leetcode

Dictionary:

leet, code

Moves:

index 0 --leet--> index 4
index 4 --code--> index 8

Return:

can_break(8) = true
can_break(4) = true
can_break(0) = true

Invariant:

can_break(i) answers whether suffix s[i:] can be segmented

Verdict:

string-index DP

Dry Run: LCS

Strings:

a = abc
b = ac

Trace:

lcs(0,0): a == a
    1 + lcs(1,1)

lcs(1,1): b != c
    max(lcs(2,1), lcs(1,2))

lcs(2,1): c == c
    1 + lcs(3,2)

Invariant:

lcs(i, j) is the best LCS length of a[i:] and b[j:]

Verdict:

two-string DP

Dry Run: Maximum Depth

Tree:

      1
     / \
    2   3
   /
  4

Return flow:

depth(4) = 1
depth(2) = 2
depth(3) = 1
depth(1) = 3

Verdict:

tree traversal with simple summary

Dry Run: Diameter

Tree:

      1
     / \
    2   3
   / \
  4   5

At node 2:

left_height = 1
right_height = 1
through_2 = 2
return height = 2

At node 1:

left_height = 2
right_height = 1
through_1 = 3
return height = 3

Verdict:

tree summary bridge

Dry Run: Build Tree From Traversals

Input:

preorder = [3, 9, 20, 15, 7]
inorder  = [9, 3, 15, 20, 7]

Step:

root = 3
left inorder = [9]
right inorder = [15, 20, 7]

Contract:

build(pre_range, in_range) returns subtree root

Verdict:

true divide/recombine

Dry Run: Count Inversions

Input:

[2, 1, 3]

Split:

[2] and [1, 3]

Merge:

compare 2 and 1:
    1 is smaller
    inversion count += 1

Return:

sorted range = [1, 2, 3]
count = 1

Verdict:

true divide/recombine with cross-boundary work

Dry Run: Segment Tree Query

Query:

sum [2, 6]

Tree:

             [0,7]
            /     \
        [0,3]     [4,7]
        /  \       /  \
    [0,1][2,3] [4,5][6,7]

Covered pieces:

[2,3] + [4,5] + [6,6]

Verdict:

range recombine

Dry Run: KMP Fallback

Pattern:

ababac

Text prefix:

ababax

At mismatch:

matched = ababa
fallback border = aba

Meaning:

Do not restart from zero.
Reuse the largest prefix that is also a suffix.

Verdict:

string automaton traversal

Dry Run: Palindrome Center

String:

ababa

Center:

index 2

Expansion:

left=1, right=3 -> b == b
left=0, right=4 -> a == a
left=-1, right=5 -> stop

Verdict:

string center traversal

Wrong Classification Mini Cases

Number of Islands

Wrong:

divide/recombine

Better:

pure explorer

Reason:

The child calls mark land. Parent does not need child summaries to rebuild an answer.

Count Inversions

Wrong:

simple exploration

Better:

divide/recombine

Reason:

The parent needs sorted child summaries to count cross pairs.

Wrong:

string matching first

Better:

state exploration first

Reason:

The hard part is grid path plus visited cells.

Word Break

Wrong:

substring brute force

Better:

string-index DP

Reason:

Once index is known, the suffix answer is fixed.

Build Tree

Wrong:

ordinary traversal

Better:

divide/recombine

Reason:

The call owns traversal ranges, splits them, and returns a subtree root.

Diameter

Wrong:

pure traversal only

Better:

tree summary bridge

Reason:

The traversal is simple, but child heights are combined through the current node.

Longest Duplicate Substring

Wrong:

plain DP

Better:

string structure plus ordered search

Reason:

The useful memory is substring equality by hash/suffix structure, and length is searched.

Decision Rules

Fast Pattern Choice

Does it ask for all concrete constructions?
    yes -> choice explorer / backtracking

Does it mainly mark reachable nodes/cells?
    yes -> pure explorer

Does it ask for shortest equal-cost moves?
    yes -> BFS explorer

Can multiple paths reach the same future state?
    yes -> DP explorer

Does the state include a small set?
    yes -> bitmask representation may help

Is the primary state string index/pair/path/center/interval/automaton?
    yes -> string state explorer, then choose engine

Does parent need child summaries?
    yes -> tree summary bridge or divide/recombine

Is there cross-boundary work?
    yes -> true divide/recombine

Backtracking Or DP

Choose backtracking when:

  • concrete paths are output
  • all valid constructions are needed
  • path mutation must be undone

Choose DP when:

  • output is count, boolean, min, or max
  • repeated states exist
  • prior path does not change the future answer

Question:

If two different paths reach this same state, is the future answer identical?

If yes, use DP.

DFS Or BFS

Choose BFS when:

  • every move has equal cost
  • shortest distance is required
  • target state can be recognized

Choose DFS/backtracking when:

  • enumeration is needed
  • a full construction must be explored
  • shortest distance is not the main output

Traversal Or Recombine

Choose traversal when:

the call mostly moves, marks, or checks

Choose recombine when:

the parent cannot answer without child summaries

Ask:

What does the child return that the parent cannot compute otherwise?

If the answer is nothing substantial, it is probably exploration.

Common Failure Modes

Incomplete State

Symptom:

valid paths are rejected or invalid paths are accepted

Cause:

state misses a fact that changes future moves

Examples:

wrong:
    (row, col)

right for key grid:
    (row, col, keys_mask)

wrong:
    word index omitted from Word Search

right:
    row, col, word_index, visited cells

Oversized State

Symptom:

memo rarely hits

Cause:

state includes irrelevant history

Fix:

remove fields that do not change the future answer

Missing Undo

Symptom:

sibling branches contain choices from earlier branches

Fix:

mutate
recurse
undo

Wrong BFS Visited Timing

Symptom:

queue grows with duplicate states

Fix:

mark visited when pushing, not when popping

Wrong Engine For Weighted Moves

Symptom:

BFS returns fewer edges but higher total cost

Fix:

use weighted shortest path logic

Calling Everything Divide/Recombine

Symptom:

you invent a combine step, but child calls only mark visited states

Fix:

use pure exploration

Calling Everything Traversal

Symptom:

the parent needs child facts but the helper does not return enough information

Fix:

define the child summary contract

Missing Cross-Boundary Work

Symptom:

left and right answers are correct but parent answer is too small

Examples:

maximum subarray:
    forgot left suffix + right prefix

count inversions:
    forgot cross pairs

Wrong String Classification

Symptom:

too much string machinery or too much brute force

Fix:

name the string state first:
index, pair, path, center, interval, trie node, automaton, or window

Performance Notes

Start with correctness. Then optimize in this order:

1. Choose the right execution family.
2. Make the state complete.
3. Make the state minimal.
4. Prune illegal branches early.
5. Memoize repeated states.
6. Use bitmasks for small sets.
7. Encode BFS states compactly.
8. Use arrays for dense DP.
9. Use child summaries to avoid recomputing cross work.

Pure Explorer Performance

Useful improvements:

  • mark before recursing
  • avoid revisiting states
  • encode grid positions as integers when large
  • use iterative stack/queue if recursion depth is risky
  • reuse direction arrays

Backtracking Performance

Useful improvements:

  • mutate one path
  • copy only complete answers
  • prune before recursion
  • sort candidates when it enables early break
  • skip duplicate sibling choices
  • use bitmasks or boolean arrays for used sets

Constraint Search Performance

Useful improvements:

  • maintain O(1) legality trackers
  • choose the most constrained variable first
  • undo trackers in reverse order
  • precompute candidate sets when stable

DP Performance

Useful improvements:

  • use tuple keys only for complete states
  • compress dimensions when recurrence permits
  • use arrays for dense states
  • use top-down for sparse states
  • use bottom-up for predictable dense states

BFS Performance

Useful improvements:

  • mark visited when pushing
  • encode bounded states as integers
  • stop when target is popped
  • use bidirectional BFS when neighbor generation is symmetric
  • include all future-changing fields in visited

Compact key example:

state_id = ((mask * rows) + row) * cols + col

String State Performance

Useful improvements:

  • memoize string indexes or (i, j) pairs
  • precompute palindrome intervals if many checks are needed
  • use trie prefixes to prune dictionary searches
  • use border/failure links for repeated pattern matching
  • use rolling hash carefully when many substring equality checks are needed

Divide/Recombine Performance

Useful improvements:

  • return the exact summary parent needs
  • avoid recomputing child summaries
  • keep endpoint convention consistent
  • do cross-boundary work while child summaries are ordered or indexed
  • ensure parent returns the same summary type upward

Cheat Sheets

Universal Checklist

Goal:
    What must be returned?

State/unit:
    What does one call own?

Moves/splits:
    What can happen next?

Stop/base:
    When does the call finish directly?

Return:
    What flows back or gets recorded?

Engine:
    pure traversal, backtracking, DP, BFS, string structure, or recombine?

Pure Explorer Checklist

What marks a state as processed?
What neighbors are legal?
What stops movement?
Can each state be processed once?
Does the traversal need to return more than mark/count/boolean?

Choice Explorer Checklist

What path am I building?
What are legal choices?
When do I record?
What do I mutate?
What do I undo?

Constraint Explorer Checklist

What trackers make legality O(1)?
Do I check before mutating?
Do I update every tracker?
Do I undo every tracker?
Can I choose a more constrained variable first?

Bitmask Checklist

Can each item map to a stable bit?
What does bit i mean?
What is the all-done mask?
Does mask belong in memo or visited?
Is 2^n feasible?

DP Checklist

What is solve(state)?
What is the memo key?
What are base cases?
What are transitions?
What combines child answers?
Can memory be compressed?

BFS Checklist

Are moves equal cost?
What is the start state?
What is the target test?
What belongs in visited?
Do I mark when pushing?
Can I bound or encode states?

String State Checklist

Is state an index, pair, path, center, interval, trie node, automaton, or window?
What character operation moves it?
Does the state repeat?
Does it need undo?
Does reusable string memory avoid repeated comparisons?

Divide/Recombine Checklist

What unit does one call own?
What is the base case?
How does the unit split?
What does each child return?
Is there cross-boundary work?
How does the parent combine?
Does the parent return the same summary type?

One-Line Hooks

  • Pure explorer: mark and move.
  • Choice explorer: choose, recurse, undo.
  • Constraint explorer: try only legal choices.
  • Bitmask state: set becomes integer.
  • DP explorer: repeated state gets cached.
  • BFS explorer: shortest equal-cost path comes from layers.
  • String state: index/pair/path/automaton moves through characters.
  • Tree summary: child facts return through parent.
  • Divide/recombine: split, solve children, combine summaries.

Final Debug Prompt

Before submitting, ask:

If I pause at this exact state or unit, do I know everything needed to solve the rest?

If no, add the missing state field or summary field.

Then ask:

Is my main work moving forward, caching repeated futures, or rebuilding upward?

The answer tells you the engine.