Skip to content
GKgkml.dev
← Pattern lab

Backtracking

Build a candidate, recurse, undo. Prune early or it explodes.

The tell: 'All permutations', 'all subsets', 'all valid combinations', N-Queens, sudoku.

Reach for it when

  • Subsets and combinations
  • Permutations with or without duplicates
  • N-Queens and sudoku solving
  • Word search on a grid
  • Palindrome partitioning

Reference implementation

subsets — choose / explore / un-choose
def subsets(nums: list[int]) -> list[list[int]]:
    result: list[list[int]] = []
    path: list[int] = []

    def backtrack(start: int) -> None:
        result.append(path[:])          # copy — path is mutated after this
        for i in range(start, len(nums)):
            path.append(nums[i])
            backtrack(i + 1)
            path.pop()                  # un-choose

    backtrack(0)
    return result

Complexity: Exponential by nature — O(2^n) subsets, O(n!) permutations. Pruning is the whole game.

What goes wrong

  • Appending `path` instead of `path[:]` — every result ends up empty because they share one list.
  • Recursing from `start` instead of `i + 1`, which produces combinations with repetition.
  • Not sorting first when de-duplicating, so the `nums[i] == nums[i-1]` skip cannot work.

Practise on

  • Subsets
  • Permutations II
  • Combination Sum
  • N-Queens
  • Word Search