Problem

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.

Examples

Example 1:

Input: nums = [1,2,3], target = 4
Output: 7
Explanation:
The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
Note that different sequences are counted as different combinations.

Example 2:

Input: nums = [9], target = 3
Output: 0

Note

This is not Combination sum problem, but Permutation Sum Problem, because [1,1,2] and [2,1,1] are treated differently.

Solution

Method 1 - Recursion

This is the recursion tree:

Code

Java
public int combinationSum4(int[] nums, int target) {
    if (target == 0) {
        return 1;
    }
    int count = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums [i] <= target)
            count += combinationSum4 (nums, target - nums [i]);
    }
    return count;
}

Method 2 - Top Down DP with Memoization

We can see repeating subproblems - for eg. see the node 3, in recursion tree in method 1.

Code

Java
public int combinationSum4(int[] nums, int target) {
	int[] dp = new int[target + 1];
	Arrays.fill(dp, -1);
	dp[0] = 1;
	return backtrack(nums, dp, target);
}
private int backtrack(int[] nums, int[] dp, int sum) {
	if (sum < 0) return 0;
	if (dp[sum] != -1) return dp[sum];
	
	int total = 0;
	
	for (int num : nums) {
		total += backtrack(nums, dp, sum - num);
	}
	
	dp[sum] = total;
	return dp[sum];
}

Method 3 - Bottom up DP

This problem is similar to Coin Change with Fewest Number of Coins Given Infinite Supply. It’s a typical dynamic programming problem.

Code

Java
public int combinationSum4(int[] nums, int target) {
	if (nums == null || nums.length == 0)
		return 0;

	int[] dp = new int[target + 1];

	dp[0] = 1;

	for (int i = 1; i<= target; i++) {
		for (int num: nums) {
			if (i >= num) {
				dp[i] += dp[i - num];
			}
		}
	}

	return dp[target];
}

Here is coin change code:

public int change(int amount, int[] coins) {
	int[] dp = new int[amount + 1];
	dp[0] = 1;
	for (int coin : coins) {
		for (int i = 1; i <= amount; i++) {
			if (i >= coin) {
				dp[i] += dp[i - coin];    
			}
		}
	}
	return dp[amount];
}

You may find the solution to this problem is basically the same with that, except the order of for loop.