You are given an array of distinct integers nums and a target integer target, return the number of possible combinations that add up to target.
The test cases are generated so that the answer can fit in a 32-bit integer.
Example 1:
Input: nums = [3,1,2], target = 4
Output: 7Explanation: The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
Example 2:
Input: nums = [1], target = 3
Output: 1Constraints:
1 <= nums.length <= 2001 <= nums[i], target <= 1000nums are unique.Follow up: What if negative numbers are allowed in the given array? How does it change the problem? What limitation we need to add to the question to allow negative numbers?
Before attempting this problem, you should be comfortable with:
We need to count all possible combinations (with different orderings counted separately) that sum to the target. At each step, we can pick any number from the array and subtract it from our remaining sum. This naturally leads to a recursive approach where we try every number at each position.
0, we found a valid combination, return 1.Where is the size of the array and is the given target.
The recursive solution has overlapping subproblems since the same remaining total can be reached through different paths. By caching results for each total value, we avoid redundant computations. This memoization transforms exponential time complexity into polynomial.
memo[0] = 1.class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
nums.sort()
memo = { 0 : 1 }
def dfs(total):
if total in memo:
return memo[total]
res = 0
for num in nums:
if total < num:
break
res += dfs(total - num)
memo[total] = res
return res
return dfs(target)Where is the size of the array and is the given target.
Instead of working backwards from the target, we can build up the solution by computing the number of ways to reach each sum from 0 to target. For each sum, we check all numbers in the array and add the ways to reach the sum minus that number.
dp[0] = 1 (one way to make sum 0: use nothing).1 to target.dp, add that count to dp[total].dp[target] as the final answer.Where is the size of the array and is the given target.
We can also work backwards from the target. Starting at the target, each number represents how many ways we can reach the target from that sum. When we subtract a number from the current total, we propagate the count to the resulting sum.
dp[target] = 1.1.dp[total] to dp[total - num].dp[0], which accumulates all ways to reach sum 0 starting from target.Where is the size of the array and is the given target.
This problem counts permutations (order matters), not combinations. [1,2,1] and [1,1,2] are counted separately. If you iterate over elements and track an index to avoid reusing earlier elements, you'll miss valid orderings.
# Wrong: treats [1,2,1] and [2,1,1] as the same
dfs(i + 1, total - nums[i])
# Correct: always start from index 0 to allow all orderings
for num in nums:
res += dfs(total - num)Forgetting to return 1 when total == 0. This base case represents finding one valid way to form the target. Returning 0 here causes all counts to be zero.
When using bottom-up DP with a hashmap, accessing dp[total - num] when total - num is negative or doesn't exist causes errors. Always check bounds or use get() with a default value.
# Wrong: KeyError if total - num < 0 or not in dp
dp[total] += dp[total - num]
# Correct: use default value
dp[total] += dp.get(total - num, 0)