Combination Sum

The problem description can be found in LeetCode.

Approach

This is a classic problem where Backtracking can be applied.

In fact, we can check all possible combination of numbers that will sum up to the target. As soon as our current sum goes below 0, it means that we can discard that path. This is true because all numbers are between 2 and 40.

Solution

from typing import List


class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        def dfs(i: int, amount: int, path: List[int], paths: List[List[int]]) -> None:
            if amount == 0:
                paths.append(path.copy())
                return
            if amount < 0 or i >= len(candidates):
                return

            for j in range(i, len(candidates)):
                path.append(candidates[j])
                dfs(j, amount - candidates[j], path, ans)
                path.pop()

        ans: List[List[int]] = []
        dfs(0, target, [], ans)

        return ans

Complexity

Let's consider the following example:

candidates = [1, 2, 5]
target = 5

This would produce the following space tree:

exampleroot*l1_11root--l1_1l1_22root--l1_2l1_55root--l1_5l2_11l1_1--l2_1l2_22l1_1--l2_2l2_55l1_1--l2_5l3_11l2_1--l3_1l3_22l2_1--l3_2l3_55l2_1--l3_5l3_2_12l2_2--l3_2_1l4_11l3_1--l4_1l4_22l3_1--l4_2l4_55l3_1--l4_5l5_11l4_1--l5_1l5_22l4_1--l5_2l5_55l4_1--l5_5

As for any DFS problem, the space complexity will be proportional with the height of the tree, which can be at most 5, hence .

Regarding the time complexity, since the maximum height is , the maximum number of nodes in the tree is , where is the size of the candidates list. Plus, we also need to consider the extra work we make to add a solution to the result list, which is .

  • Time:
  • Space:

Where is .