Backtracking
Think of solving a maze. You walk down a corridor, turn left, walk some more, and hit a wall. You don't give up — you backtrack to the last junction and try the next corridor. You keep doing this, systematically, until you either find the exit or confirm there isn't one.
That's backtracking in a nutshell: build a solution one piece at a time, and the moment a partial solution violates a rule, abandon the whole branch and try something different. No need to explore what's downstream of a dead end.
The three-step heartbeat
Every backtracking algorithm beats to the same rhythm:
1. Choose — pick a candidate value for the current slot (a queen's column, a Sudoku digit, the next item to include).
2. Explore — if the choice doesn't break any constraints, recurse into the next slot.
3. Undo — after the recursion returns (whether it found a solution or hit a dead end), un-make the choice and try the next candidate. This restore step is what gives backtracking its name.
The "undo" is crucial. Without it, choices from one branch would leak into the next, corrupting the search.
N-Queens — a classic example
Place n queens on an n×n chessboard so no two attack each other. The trick: place queens row by row. At row r, try each column c. If no previously placed queen shares column c, the left diagonal, or the right diagonal — place the queen and recurse to row r+1. When you return, remove the queen and try column c+1.
For n=8 there are \(8^8\) ≈ 16 million raw combinations, but with pruning the algorithm visits only around 15,000 nodes — a 1000× speedup.
Sudoku
For each empty cell, try digits 1–9. Skip any digit already present in the same row, column, or 3×3 box. If a digit is consistent, fill it in and recurse to the next empty cell. If no digit works, return false and let the caller backtrack.
Add constraint propagation — after placing a digit, immediately remove it as a candidate from every peer cell — and most Sudoku puzzles solve with fewer than ten backtracks total.
Permutations and subsets
Backtracking is essentially depth-first search on a decision tree built on the fly. It naturally generates all permutations (at each position, try each unused element, mark it used, recurse, unmark) and all subsets (at each element, branch on include-or-skip). Pruning conditions like "running sum already exceeds target" cut off entire branches early.