Backtracking builds candidate solutions incrementally and abandons (backtracks from) a partial candidate as soon as it cannot lead to a valid solution. It systematically explores the solution space via DFS, pruning dead ends.
The idea
Choose -> explore -> un-choose. Try an option, recurse; if it fails, undo it and try the next.
Example: all permutations
():
result = []
():
remaining:
result.append(path[:])
i ((remaining)):
path.append(remaining[i])
backtrack(path, remaining[:i] + remaining[i+:])
path.pop()
backtrack([], nums)
result
permutations([, , ])
