Backtracking
Sum of All Subset XOR Totals
Find the sum of the XOR total of every subset of nums, subsets with the same elements counted once per distinct subset. nums = [1,3] → subsets [], [1], [3], [1,3] → XOR totals 0, 1, 3, 2 → sum 6.
DFS: include or exclude each number
dfs(i, total),iis the current index,totalis the running XOR of everything included so far.- Base case:
i == len(nums), one full subset decided, returntotal. - Recursive case: branch into two calls, one including
nums[i](XOR it intototal), one excluding it, sum both branches' results. - Every root-to-leaf path is one subset, so the sum returned at the root is the sum over all
2^nsubsets.
python
class Solution:
def subsetXORSum(self, nums: List[int]) -> int:
def dfs(i, total):
if i == len(nums):
return total
return dfs(i + 1, total ^ nums[i]) + dfs(i + 1, total)
return dfs(0, 0)timeO(2^n)spaceO(n)
Subsets
Return all possible subsets of nums (the power set), no duplicates in the input. nums = [1,2,3] → [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]].
1. Include, then exclude
subsetis the current partial subset being built, shared across the whole recursion via append/pop.dfs(i), base casei >= len(nums), the subset is complete, append a copy of it toresand return.- Decision to include
nums[i]: append it tosubset, recurse toi+1. - Decision to exclude
nums[i]: pop it back offsubset, recurse toi+1again, same branching shape as Sum of All Subset XOR Totals above, just building an actual list instead of a running XOR.
python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
subset = []
def dfs(i):
if i >= len(nums):
res.append(subset.copy())
return
# decision to include nums[i]
subset.append(nums[i])
dfs(i + 1)
# decision NOT to include nums[i]
subset.pop()
dfs(i + 1)
dfs(0)
return restimeO(n * 2^n)spaceO(n)
2. Exclude, then include
- Same two branches as above, just flipped: recurse without
nums[i]first, then append it, recurse again, and pop it back off. - Order of the two recursive calls doesn't change which subsets get found, only the order
resends up in,backtrack(i+1)before touchingsolstill visits every include/exclude combination exactly once. sol[:]is a slice-copy, does the same job assubset.copy()above, just different syntax for the same "snapshot the list before it keeps mutating" need.
python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
res, sol = [], []
def backtrack(i):
if i == n:
res.append(sol[:])
return
# Don't pick nums[i]
backtrack(i + 1)
# Pick nums[i]
sol.append(nums[i])
backtrack(i + 1)
sol.pop()
backtrack(0)
return restimeO(n * 2^n)spaceO(n)