Backtracking
For each element , we take
instances of it such that
and try to make
using other elements. We process candidates in a sorted order to be able to use a set to keep only unique combinations.
Recursion tree has height and width
. So, time:
, space:
.
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def collect(i, rem):
if rem == 0:
return [[]]
if rem < 0 or i == len(candidates):
return []
combs = []
x = candidates[i]
j = 0
while j * x <= rem:
for c in collect(i+1, rem-j*x):
combs.append(c + [x]*j)
j += 1
return combs
return collect(0, target)
Dynamic programming
Subproblem
Let be the combinations using elements in
nums[0:i+1] and target = . Then:
Order
Subproblems are on a -by-
grid and row-wise processing gives a topological order. However, we use top-down approach with memoization.
Time: , space:
.
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
memo = {}
def collect(i, rem):
if rem == 0:
return [[]]
if rem < 0 or i == len(candidates):
return []
if (key := (i, rem)) in memo:
return memo[key]
combs = []
x = candidates[i]
j = 0
while j * x <= rem:
for c in collect(i+1, rem-j*x):
combs.append(c + [x]*j)
j += 1
memo[key] = combs
return combs
return collect(0, target)
Leave a comment