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 d...
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)