Python backtracking and subsets
Choose, recurse, and undo to explore a decision tree.
On this page
Recursion and mutable lists.
- Choose, recurse, and undo to explore a decision tree.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
Backtracking explores alternatives while maintaining a partial choice. This subset generator first excludes an item, then includes it, and removes it before returning.
Copy the current path when recording a result. Storing the mutable path object itself would make results share the same changing list.
Code example
def subsets(values):
result = []
path = []
def visit(index):
if index == len(values):
result.append(path.copy())
return
visit(index + 1)
path.append(values[index])
visit(index + 1)
path.pop()
visit(0)
return result
print(subsets([1, 2]))
assert subsets([]) == [[]][[], [2], [1], [1, 2]]
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
def subsets(values): result = [] path = [] def visit(index): if index == len(values): result.append(path.copy()) return visit(index + 1) path.append(values[index]) visit(index + 1) path.pop() visit(0) return result print(subsets([1, 2]))assert subsets([]) == [[]]Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Begin with no selected values. | path = [] | — | |
| Exclude both values and record the empty subset. | result = [[]] | — | |
| Include 2 after excluding 1. | path = [2] | — | |
| Record [2], then undo that choice. | result = [[], [2]] | — | |
| Include 1 at the first level. | path = [1] | — | |
| Exclude 2 and record [1]; then include 2 and record [1,2]. | result = [[], [2], [1], [1, 2]] | — | |
| Undo choices while returning to the caller. | path = [] | — | |
| Print the generated subsets. | path = [] | [[], [2], [1], [1, 2]] |
Behind the scenes
How Python processes this code
Python runs this source through its interpreter. It creates objects for values and resolves names as each statement runs.
Cost and common mistakes
O(n*2^n) time and output storage; O(n) auxiliary recursion/path space excluding output.
- Omitting pop leaks a choice into later branches.
- Repeated input values can produce equal subsets; this example treats positions as distinct choices.
Try it yourself
How many subsets are produced for three distinct values?
Reveal answer and reasoning
There are 2^3 = 8, including the empty subset and the full set.