Home Interview Backtracking Interview Problems: 8 Patterns That Get Offers
Advanced 3 min · September 07, 2026
Top Backtracking Interview Problems

Backtracking Interview Problems: 8 Patterns That Get Offers

Backtracking interview guide: one template for N-Queens, Sudoku, Word Search, permutations.

N
Naren Founder & Principal Engineer

20+ years shipping production code across the stack, with years spent interviewing engineers. Lessons pulled from things that broke in production.

Follow
Production
production tested
September 22, 2026
last updated
1,799
articles · all by Naren
Before you start⏱ 28 min
  • Recursion and call-stack mental model
  • Python lists, sets, and copying semantics
  • Basic Big-O (factorial vs exponential)
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • Backtracking = one template (choose → explore → unchoose) plus one constraint check per problem
  • N-Queens prunes with column + two diagonal sets; never place an attacked queen
  • Sudoku prunes with row/col/box sets and fewest-candidates-first (MRV) cell order
  • Word Search prunes with per-path visited restore and rare-letter-first ordering
  • Permutations/subsets/combinations differ only in choice rule and duplicate skipping
  • In-place mutate-and-restore beats per-call copying by orders of magnitude past n = 15
✦ Definition~90s read
What is Top Backtracking Interview Problems?

Backtracking is the systematic trial-and-error search behind constraint problems: build a candidate step by step, abandon it the moment constraints break, and rewind to the last decision point. It powers N-Queens (92 solutions at n=8), Sudoku (9×9 Latin constraints), Word Search (grid DFS with visited restore), and the permutations/subsets/combination family — all LeetCode Hard/Medium staples with 70%+ interview appearance rates in backend loops.

Imagine exploring a maze with a ball of string: walk down a corridor (choose), and if it's a dead end, follow the string back (unchoose) and try the next corridor.

Its theory ceiling is NP-completeness (exact cover, Hamiltonian paths), but interviews test engineering, not theory: template fluency, constraint modeling, pruning judgment, and live complexity narration. Master those four and the 'hard' label stops mattering.

Plain-English First

Imagine exploring a maze with a ball of string: walk down a corridor (choose), and if it's a dead end, follow the string back (unchoose) and try the next corridor. You never redraw the whole map per attempt — you unwind your steps. Backtracking is that string: a single path you extend and retract while a rulebook (constraints) tells you which corridors are legal. N-Queens' rulebook bans shared diagonals, Sudoku's bans duplicate digits in a row, column, or box, and Word Search's bans reusing a cell. Same string, different rulebook.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

Backtracking owns the hardest 15 minutes of coding interviews. N-Queens, Sudoku, Word Search, permutations — you've seen them on every 'top problems' list, and you still can't be sure you'd solve one live. Don't memorize four solutions. You'll drown. Learn one template and four constraint checks instead.

Here's the uncomfortable truth: every backtracking problem is the same three lines — choose, explore, unchoose — wrapped around a different validity test. Candidates who memorize boards fail the moment the interviewer tweaks the rules. Candidates who own the template adapt in seconds. Speed matters.

This guide gives you that template, then instantiates it four ways with runnable sketches: N-Queens with diagonal sets, Sudoku with box constraints, Word Search with visited restore, and the permutations/subsets/combination family. You'll also get pruning math that answers 'will this pass?' and an execution playbook for the whiteboard.

The One Template — Choose, Explore, Unchoose

All four problems compile to this skeleton. The base case records a snapshot. The loop enumerates candidates, prunes invalid ones BEFORE recursing, then does the three-beat: mutate, recurse, restore. Bugs live in exactly three places: missing snapshot (aliasing), missing restore (dirty state), prune-after-recurse (exponential blowup).

The problem-specific slots: candidates() is 'columns in this row' (Queens), 'digits 1-9' (Sudoku), '4 neighbors' (Word Search), 'unused elements from index i' (subsets). valid() is diagonal sets, box sets, visited+letter match, take/skip rules. Fill two slots, get a solution.

Practice drill: write the skeleton from memory 5 times, then fill Queens constraints without looking. That drill alone converts most 'I freeze' candidates into passers.

backtrack_template.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
def backtrack(path, choices):
    if goal_reached(path):          # base case: record a snapshot
        results.append(list(path))
        return
    for c in candidates(choices):   # choice rule differs per problem
        if not valid(path, c):      # constraint check differs per problem
            continue                # prune: never recurse into dead branches
        path.append(c)              # CHOOSE
        backtrack(path, updated(choices, c))
        path.pop()                  # UNCHOOSE (restore!)

# Grid flavor: mark cell -> recurse 4 neighbors -> unmark cell.
# Set flavor:  add to used  -> recurse next index -> remove from used.
💡Memorize This, Derive Everything Else
If you can't write these 8 lines cold, you're not ready — everything else is slot-filling.
📊 Production Insight
Interviewers watch the first 90 seconds: candidates who write the skeleton first signal structure and get hints; candidates who dive into board details get silence. Template-first is a scoring signal, not just style.
🎯 Key Takeaway
Skeleton is fixed; only candidates() and valid() change per problem.

N-Queens — Diagonal Sets Do the Pruning

Place one queen per row; the choice is the column. Constraints: no shared column, no shared ↙↗ diagonal (r−c equal), no shared ↖↘ diagonal (r+c equal). Three sets enforce all of it in O(1) per candidate.

Pruning power: row 0 tries n columns, but row 1 tries only n−2 or fewer — attacked columns and diagonals vanish before recursion. n=8 yields 92 solutions in milliseconds; the raw n^n fantasy (16M placements) never materializes because most branches die at depth 2.

Interview narration: 'one queen per row, three sets, snapshot the board at depth n.' That's a 60-second explanation that scores full marks on structure before you write a line.

n_queens_sketch.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def solve_n_queens(n):
    res, cols, d1, d2, queens = [], set(), set(), set(), []
    def bt(r):
        if r == n:
            res.append(['.' * c + 'Q' + '.' * (n - 1 - c) for c in queens])
            return
        for c in range(n):
            if c in cols or (r - c) in d1 or (r + c) in d2:
                continue  # prune attacked squares before recursing
            cols.add(c); d1.add(r - c); d2.add(r + c); queens.append(c)
            bt(r + 1)
            queens.pop(); cols.discard(c); d1.discard(r - c); d2.discard(r + c)
    bt(0)
    return res  # n=4 -> 2 solutions; n=8 -> 92
🔥Diagonals Are Arithmetic
r − c is constant on ↙↗ diagonals, r + c on ↖↘. That's the whole trick — three sets.
📊 Production Insight
n=4 → 2 solutions is the canonical self-test: wrong diagonal arithmetic over-counts (4+) or returns zero. Run it before touching n=8.
🎯 Key Takeaway
Three O(1) sets prune each row to surviving columns; snapshot boards at depth n.

Sudoku Solver — Box Sets Plus MRV Ordering

State: 9×9 board plus row/col/box digit sets. Choice: digit for the emptiest-constrained cell. Prune: digits already present in any of the three units never recurse. MRV ordering (minimum remaining values) picks the most constrained cell first, so contradictions surface at shallow depth.

Why MRV wins: a cell with 1 candidate forces the move; a cell with 7 candidates guesses. Row-major order guesses early and backtracks late — exponential waste. MRV on hard puzzles cuts solve time from seconds to milliseconds.

Box index arithmetic (r//3)*3 + c//3 maps 81 cells to 9 boxes. Get it wrong and valid boards reject — test box mapping on corners (0,0)→0, (0,8)→2, (8,0)→6, (8,8)→8 before running the solver.

sudoku_sketch.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def solve_sudoku(board):
    rows = [set() for _ in range(9)]
    cols = [set() for _ in range(9)]
    boxes = [set() for _ in range(9)]
    empties = []
    for r in range(9):
        for c in range(9):
            v = board[r][c]
            if v == '.':
                empties.append((r, c))
            else:
                rows[r].add(v); cols[c].add(v)
                boxes[(r // 3) * 3 + c // 3].add(v)
    def candidates(r, c):
        used = rows[r] | cols[c] | boxes[(r // 3) * 3 + c // 3]
        return [d for d in '123456789' if d not in used]
    def bt(k):
        if k == len(empties):
            return True
        # MRV: pick emptiest-constrained cell among remaining
        nxt = min(range(k, len(empties)),
                  key=lambda i: len(candidates(*empties[i])))
        empties[k], empties[nxt] = empties[nxt], empties[k]
        r, c = empties[k]
        for d in candidates(r, c):
            board[r][c] = d
            rows[r].add(d); cols[c].add(d)
            boxes[(r // 3) * 3 + c // 3].add(d)
            if bt(k + 1):
                return True
            board[r][c] = '.'
            rows[r].discard(d); cols[c].discard(d)
            boxes[(r // 3) * 3 + c // 3].discard(d)
        return False
    bt(0)
    return board
⚠ Cell Order Matters More Than Digit Order
MRV (fewest candidates first) is worth 10-100x. Hardcoded row-major order is the #1 Sudoku TLE.
🎯 Key Takeaway
Three unit-sets prune digits; MRV cell order prunes the search order itself.

Word Search — In-Place Visited With Restore

State: grid position plus matched-prefix length. Choice: 4 neighbors. Constraints: in-bounds, letter match, not visited (the '#' sentinel). Mark in place — no visited matrix copies — and restore on exit so sibling paths see a clean board.

Pruning that interviewers love: start DFS only from cells matching word[0]; rarer first letters prune harder. Early exits on length (word longer than cells) and letter-frequency counts (board lacks enough 'Z's) kill impossible cases in O(R×C) before any DFS.

Complexity honesty: worst case O(R×C×3^L) (4 first moves, ~3 thereafter excluding backtrack), but letter-match pruning collapses real boards. Say both numbers — the bound and why practice beats it.

word_search_sketch.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def exist(board, word):
    R, C = len(board), len(board[0])
    def dfs(r, c, i):
        if i == len(word):
            return True
        if not (0 <= r < R and 0 <= c < C) or board[r][c] != word[i]:
            return False
        tmp = board[r][c]
        board[r][c] = '#'  # mark visited in place (no copied matrix)
        found = (dfs(r + 1, c, i + 1) or dfs(r - 1, c, i + 1)
                 or dfs(r, c + 1, i + 1) or dfs(r, c - 1, i + 1))
        board[r][c] = tmp  # UNCHOOSE: restore for sibling paths
        return found
    for r in range(R):
        for c in range(C):
            if board[r][c] == word[0] and dfs(r, c, 0):
                return True
    return False
⚠ Visited Discipline
Mark-then-check order and unmark-on-exit are both load-bearing. Swap either and cells leak.
🎯 Key Takeaway
Sentinel-mark in place, restore on exit; start cells and frequency checks prune first.

Permutations, Subsets, Combination Sum — One Family

Permutations choose an ordering (used-array, any unused element); subsets choose membership (start-index, take-or-skip from i); Combination Sum adds a target with sorted early-stop (stop when remainder < 0) and same-index reuse for unlimited picks.

Duplicate handling is one rule: sort, then skip nums[i] when its twin nums[i−1] sits unused at the same level. That single line fixes Permutations II, Subsets II, and Combination Sum II identically.

Narrate the family mapping in interviews: 'permutations vary order, subsets vary membership, combinations add a sum target — same skeleton, different candidate rule.' Interviewers promote candidates who see families.

perm_subsets_sketch.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def permute_unique(nums):
    nums.sort()
    res, used, path = [], [False] * len(nums), []
    def bt():
        if len(path) == len(nums):
            res.append(list(path))
            return
        for i in range(len(nums)):
            if used[i]:
                continue
            if i > 0 and nums[i] == nums[i - 1] and not used[i - 1]:
                continue  # skip same-level twins (duplicate prune)
            used[i] = True
            path.append(nums[i])
            bt()
            path.pop()
            used[i] = False
    bt()
    return res

def subsets(nums):
    res, path = [], []
    def bt(i):
        res.append(list(path))  # every node is a valid subset
        for j in range(i, len(nums)):
            path.append(nums[j])
            bt(j + 1)  # start-index: never revisit earlier elements
            path.pop()
    bt(0)
    return res  # 2^n subsets
💡One Skip Rule, Three Problems
Sorted + skip-twins converts three problems (perm/subset/combo) from duplicates hell to clean output.
🎯 Key Takeaway
Order vs membership vs target: same skeleton, one duplicate-skip rule, sorted early-stop.

Pruning and Complexity — Answering Will This Pass

Raw bounds terrify: N-Queens O(n^n) placements, Sudoku O(9^81), Word Search O(4^L), permutations O(n!). Pruned reality: Queens places 92 solutions for n=8 in milliseconds, MRV Sudoku solves hard boards in milliseconds, Trie-guided Word Search II handles thousands of words on 12×12 boards.

The interview move is naming the effective branching: 'each queen kills a column and two diagonals, so depth-k branching is roughly n−2k'; 'MRV keeps Sudoku at 1–3 candidates per cell'; 'Trie guidance leaves ~1 live neighbor per Word Search step.' Numbers beat adjectives.

Time-box rule: if your search hasn't collapsed by depth 2, stop coding and add a constraint. No amount of micro-tuning saves unpruned exponential search — structure first, speed second.

pruning_checklist.pyPYTHON
1
2
3
4
5
6
7
# Pruning checklist — apply before claiming a solution passes:
# 1. N-Queens:   cols/diag sets      -> branching n -> ~n-2k at depth k
# 2. Sudoku:     row/col/box + MRV    -> 9 -> 1-3 typical candidates
# 3. Word Search: letter match + Trie -> 4 -> ~1 live neighbor
# 4. Combination: sorted + early stop -> unbounded -> bounded by target
# Time-box rule: if depth-2 branching isn't visibly collapsing, add a
# constraint BEFORE optimizing code. Structure beats micro-tuning.
🔥The Complexity Sentence
'O(n!) worst case, collapsing to milliseconds after sets/MRV/Trie pruning' — say this sentence verbatim.
🎯 Key Takeaway
Quote raw bounds, then effective branching after pruning; structure beats tuning.

Interview Execution Playbook — How to Present It Live

Minute 0–2: write the skeleton and label the two slots (candidates, valid). Interviewers score this instantly — it proves you've solved the class, not just an instance. Minutes 2–7: fill the slots with the constraint sets, narrating each ('columns, two diagonals').

Minutes 7–10: state complexity with pruning and run the smallest discriminating test (n=4 Queens → 2; 2×2 grid; [1,1,2] → 3 perms). Small tests catch diagonal arithmetic, aliasing, and skip-rule bugs in seconds.

Remaining time: invite follow-ups ('want duplicates handled? Trie-guided multi-word?'). Candidates who finish the core in 10 minutes and spend 20 on variants get hired; candidates who perfect one board for 40 minutes don't.

interview_playbook.pyPYTHON
1
2
3
4
5
6
7
8
# Whiteboard execution order (say each step out loud):
# 1. Write skeleton: base case + loop + choose/recurse/unchoose (2 min)
# 2. Fill candidates() + valid() for THIS problem (5 min)
# 3. State complexity WITH pruning + name the pruning (1 min)
# 4. Self-test: n=4 queens / tiny grid / [1,1,2] perms (3 min)
# 5. Follow-ups: duplicates? bigger board? Trie guidance? (remaining)
# Red flags to voice early: copying state per call, appending live refs,
# pruning after recursion, hardcoded cell order in Sudoku.
💡The 45-Minute Budget
Template (2 min) → constraints (5 min) → self-test (3 min) → follow-ups. That's the 45-minute budget.
🎯 Key Takeaway
Skeleton first, constraints second, tiny self-test third, variants with leftover time.
● Production incidentPOST-MORTEMseverity: high

The Memorized N-Queens That Died on Word Search

Symptom
30 minutes, zero passing code: first a blank whiteboard ('I know this one...'), then a solution copying the visited matrix per call that timed out on a 12×12 board, then time expiry before Trie pruning was attempted.
Assumption
The candidate assumed memorized N-Queens code would transfer to a Word Search variant, and that copying visited sets per call was 'cleaner'. They never practiced the template blind, so under pressure there was no template — only fragments.
Root cause
Two failures: no portable template (memorized board code didn't map to grid DFS), and O(n) visited-copy per node turned 4-directional search into a memory and time blowup. The candidate also never pruned by Trie guidance, so thousands of words each triggered full-grid DFS.
Fix
Rebuilt from the three-line template (mark → recurse → unmark) in 8 minutes and passed. Logged rule: no backtracking problem is 'known' until you can write its template cold and fill constraints on demand — variants are the norm, not the exception.
Key lesson
  • Interviewers mutate known problems deliberately — templates survive, memorized boards don't.
  • Copying state per call is a TLE time bomb; in-place restore is non-negotiable past n = 15.
  • Say the complexity WITH pruning before coding; it buys trust and guides cell ordering.
Production debug guideThree backtracking failure signatures and the exact fix for each.3 entries
Symptom · 01
Results are empty or all identical despite correct-looking recursion
Fix
Add a depth counter and print the path at each append. Then check two things: (1) every append uses list(path) or equivalent snapshot; (2) every loop body ends with pop/unmark. Re-run N-Queens n=4 — exactly 2 distinct boards means both hold.
Symptom · 02
Correct output locally on tiny inputs, TLE on real sizes
Fix
Print branching factor per level for 30 seconds. If level 1 already fans to n with no constraint check before the recursive call, move the validity test above the call (or precompute candidates). For Sudoku, switch cell order to fewest-candidates-first and re-time — expect 10-100x speedup.
Symptom · 03
Solver returns boards that violate the rules on larger inputs
Fix
Isolate one constraint at a time: run N-Queens with only column checks (expect over-count), then add each diagonal. For Sudoku, validate the final board with a checker (rows/cols/boxes sets) to find which constraint leaked. The failing constraint is always the last one added — recheck its undo line.
Backtracking Problems: Pattern at a Glance
ProblemStateChoicePruning signal
N-QueensRows placed + attacked setsColumn per rowColumn/diagonal sets — never place attacked queens
Sudoku SolverEmpty cells filledDigit 1-9 per cellRow/col/box constraints + MRV cell order
Word SearchMatched prefix + position4 neighborsVisited set + first-letter/rarity ordering
PermutationsUsed flags + current orderUnused elementUsed-set skips duplicates via sorted + prev-skip
Subsets / Combination SumIndex + current setTake or skip nums[i]Start-index (no revisits) + sorted early-stop on target
⚙ Quick Reference
5 commands from this guide
FileCommand / CodePurpose
backtrack_template.pydef backtrack(path, choices):The One Template
n_queens_sketch.pydef solve_n_queens(n):N-Queens
sudoku_sketch.pydef solve_sudoku(board):Sudoku Solver
word_search_sketch.pydef exist(board, word):Word Search
perm_subsets_sketch.pydef permute_unique(nums):Permutations, Subsets, Combination Sum

Key takeaways

1
Every backtracking solution is choose → explore → unchoose around a validity test.
2
Mutate path state in place and restore it; never copy per call.
3
Append snapshots (list(path)), never live references, to results.
4
Pruning (constraint sets, MRV, Trie guidance) is what makes exponential pass.
5
State the pruned complexity and the order you'll code
template first, constraints second.

Common mistakes to avoid

4 patterns
×

Copying the path or visited set on every recursive call

Symptom
Subsets on n = 20 takes 30+ seconds and 2 GB — O(n) copy per node over 2^n nodes. Correct output, TLE verdict. In-place mutate-and-restore is the entire performance game.
Fix
Copy the loop skeleton and mutate the path in place: append → recurse → pop. For grids, mark visited → recurse → unmark. No copies of path/visited inside the loop. Verify with subsets on [1,2,3]: 8 results, each list object distinct at append time via list(path).
×

Appending the live path reference instead of a snapshot

Symptom
N-Queens returns 2 'solutions' that are both empty (or all identical). The result list holds n references to one mutated list. Passes counts if you count, fails content if anyone reads it.
Fix
Append list(path) (or ''.join / tuple) — a snapshot. Then pop and continue. Audit every append line: if it lacks a copy constructor, it is a bug. Test N-Queens n=4 expecting exactly 2 solutions to catch aliasing instantly.
×

Checking constraints after recursing instead of before, or forgetting to undo them

Symptom
Sudoku solver returns an invalid board (duplicate in a row) or Word Search matches words through reused cells. Output looks plausible until validated — the worst kind of wrong.
Fix
For N-Queens track cols, diag1 (r-c), diag2 (r+c) sets with add/recurse/discard. For Sudoku check row/col/box before recursing and undo on backtrack. For Word Search mark the cell BEFORE the letter check of neighbors and unmark after. No cell is ever read in a dirty state.
×

Quoting O(n!) / O(9^81) complexity with no pruning analysis

Symptom
Interviewer asks 'will this pass?' and you have no answer — you memorized the bound but can't argue why n=9 Sudoku solves in milliseconds. Senior candidates discuss effective branching after constraints; juniors recite factorials.
Fix
State the pruning contract per problem: N-Queens prunes by column/diagonal sets (never places an attacked queen); Sudoku prunes by candidate elimination + MRV cell choice; Word Search prunes by first-letter frequency and early length checks. Then analyze the PRUNED tree, not the raw b^n fantasy.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How do you handle duplicates in permutations?
Q02SENIOR
Word Search II has thousands of words — how do you scale?
Q03SENIOR
You have never seen this backtracking problem before. How do you start l...
Q01 of 03SENIOR

How do you handle duplicates in permutations?

ANSWER
Reference solution: sort + used array, skip nums[i] when nums[i]==nums[i-1] and not used[i-1] (same-level twin skip). Complexity stays factorial in the worst case but emits each distinct permutation once. Mention it proves you think about input classes, not just happy paths.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
I freeze on backtracking problems in live interviews. What helps?
02
Do permutations change when the input has duplicates?
03
Is grid visited handling different from used-array handling?
04
Are these problems NP-complete? Should I mention that?
05
What should I solve after mastering these four?
N
Naren Founder & Principal Engineer

20+ years shipping production code across the stack, with years spent interviewing engineers. Lessons pulled from things that broke in production.

Follow
Verified
production tested
September 22, 2026
last updated
1,799
articles · all by Naren
🔥

That's Coding Patterns. Mark it forged?

3 min read · try the examples if you haven't

Previous
CI/CD Interview Questions
18 / 18 · Coding Patterns