# 0377. Combination Sum IV

https://leetcode.com/problems/combination-sum-iv

## Description

Given an array of **distinct** integers `nums` and a target integer `target`, return _the number of possible combinations that add up to_ `target`.

The answer is **guaranteed** to fit in a **32-bit** integer.

**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
```

**Constraints:**

* `1 <= nums.length <= 200`
* `1 <= nums[i] <= 1000`
* All the elements of `nums` are **unique**.
* `1 <= target <= 1000`

**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?

## ac1: top-down DP, DFS + memorization

similar: [https://leetcode.com/problems/coin-change/description/](https://leetcode.com/problems/coin-change/description/)

```java
class Solution {
    Map<Integer, Integer> map = new HashMap<>();

    public int combinationSum4(int[] nums, int target) {
        // exit
        if (target == 0) return 1;  // empty is counted as 1
        if (map.containsKey(target)) return map.get(target);

        // iterate
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] <= target) {
                res += combinationSum4(nums, target-nums[i]);
            }
        }

        map.put(target, res);
        return res;
    }
}
```

## ac2: bottom-up DP

```java
class Solution {
    public int combinationSum4(int[] nums, int target) {
        // edge cases
        if (nums == null || nums.length == 0 || target <= 0) return 0;

        int[] dp = new int[target+1]; // dp[i]: how many combinations that sum up to i. 
        dp[0] = 1;

        for (int i = 1; i <= target; i++) {
            for (int j = 0; j < nums.length; j++) {
                if (i - nums[j] >= 0) {
                    dp[i] += dp[i-nums[j]];
                }
            }
        }

        return dp[target];
    }
}
// 1) dp[i]: how many combinations add up to i; 2) for each i, iterate nums.
// O(target*N) time, O(target) space
```
