Backtracking
Build solutions incrementally and undo choices that lead to dead ends — implement permutations, subsets, and N-queens with pruning.
- Implement permutations and subsets using the build-recurse-undo pattern
- Implement N-queens with constraint pruning (no conflicting rows, columns, or diagonals)
Backtracking is systematic exhaustive search with pruning. You build a candidate solution incrementally — appending one element at a time — and recurse. When the current partial solution violates a constraint, you undo the last choice (backtrack) and try the next option. This avoids generating all candidates explicitly; pruning cuts branches of the search tree early.
The template is always the same:
def backtrack(current, choices):
if is_complete(current):
record(current)
return
for choice in choices:
if is_valid(current, choice):
current.append(choice) # choose
backtrack(current, ...) # explore
current.pop() # undo (backtrack)Three backtracking implementations
The undo step matters
In permutations: current.pop() undoes the choice before trying the next
element at the same position. Without it, current would grow unboundedly
and the same elements would appear in multiple branches.
In N-queens: removing col, row - col, and row + col from the sets
before returning means the constraints of one column choice do not
"leak" into sibling branches.
Pruning is what separates efficient backtracking from blind enumeration. In
N-queens the constraint check col in cols eliminates entire sub-trees —
no need to try placing queens in attacked positions. The number of valid
placements for 8-queens is 92 out of 8^8 = 16,777,216 possible blind
placements. Pruning cuts the search tree dramatically.
Subsets vs permutations
Subsets record the partial solution at every recursive node (not just the
leaves), because an empty set and every prefix are valid answers. Permutations
only record at the leaves (when remaining is empty and the full permutation
is built). Both use the same build-recurse-undo skeleton.
Where to go next
Next: lab — paradigm problems — four problems where the first task is identifying which paradigm applies, then implementing it.
Divide and conquer
Split problems into independent sub-problems, recurse, combine — understand the pattern in merge sort, binary search, and quickselect, with an intuition for the Master Theorem.
Lab: paradigm problems
Four problems — identify the correct paradigm, then implement. Activity selection (greedy), kth largest (divide and conquer), combination sum (backtracking), and maximum subarray (DP).