Table of Contents
Backtracking š¤Æ
https://leetcode.com/problems/subsets/
Given an integer array nums of unique elements, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Example 1:
Input: nums = [1,2,3] Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
Example 2:
Input: nums = [0] Output: [[],[0]]
Solution
function subsets(nums: number[]): number[][] {
const result: number[][] = [];
function dfs(start: number, currentSubset: number[]) {
console.log("start", start, "currentSubset", currentSubset);
result.push([...currentSubset]); // important: create a copy of currentSubset instead of adding it directly
// console.log("result", result);
for (let i = start; i < nums.length; i++) {
currentSubset.push(nums[i]); // [1]
dfs(i + 1, currentSubset);
console.log("popped", currentSubset.pop(), currentSubset);
}
}
dfs(0, []);
return result;
}
console.log(subsets([1, 2, 3]));
The Decision Tree
- Each level represents a decision: We either include or exclude an element.
- Backtracking removes elements before trying a new path.
- All possible subsets are explored without duplicates.
Backtracking is just DFS on tree except there's no pre-defined tree. You have to build your own tree by passing the states through parameters.
For example, normally when you do pre-order traversal, you go root -> root.left -> root.right. In backtracking involving choosing a number, left tree will be choosing the number and right tree not choosing. So you go left first by adding the number to path, call dfs(root.left). Pop it out of path (un-choosing) then dfs(root.right).
[]
āāāāāāāāāāāā“āāāāāāāāāāā
[1] []
āāāāāāāā“āāāāāāā āāāāāāāā“āāāāāāā
[1,2] [1] [2] []
āāāāāā“āāāāā āāāā“āāā āāāā“āāā āāāā“āāā
[1,2,3] [1,2] [1,3] [1] [2,3] [2] [3] []
ā
ā¬ļø ā
ā¬ļø ā
ā¬ļø ā
ā
Backtrack Backtrack Backtrack (end)
Call stacks
- dfs(0, [])
- āāā dfs(1, [1])
- ā āāā dfs(2, [1,2])
- ā ā āāā dfs(3, [1,2,3])
- ā ā āāā Returns to dfs(2, [1,2])
- ā āāā dfs(3, [1,3])
- ā āāā Returns to dfs(1, [1])
- āāā dfs(2, [2])
- ā āāā dfs(3, [2,3])
- ā āāā Returns to dfs(2, [2])
- āāā dfs(3, [3])
- āāā Returns to dfs(0, [])
Paths
1st Path (Include Everything)
[] ā [1] ā [1,2] ā [1,2,3] ā
(added to result)
ā¬ļø backtrack (remove 3)
ā [1,2] ā
(added to result)
ā¬ļø backtrack (remove 2)
ā [1,3] ā
(added to result)
ā¬ļø backtrack (remove 3)
ā [1] ā
(added to result)
ā¬ļø backtrack (remove 1)
2nd Path (Start with 2)
[] ā [2] ā [2,3] ā
(added to result)
ā¬ļø backtrack (remove 3)
ā [2] ā
(added to result)
ā¬ļø backtrack (remove 2)
3rd Path (Start with 3)
[] ā [3] ā
(added to result)
ā¬ļø backtrack (remove 3)
haochen xu