377. Combination Sum IV

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了377. Combination Sum IV相关的知识,希望对你有一定的参考价值。

Given an integer array with all positive numbers and no duplicates, 
find the number of possible combinations that add up to a positive integer target. Example: nums
= [1, 2, 3] target = 4 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. Therefore the output is 7. 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?
暴力法转化为动归---top down---memory search: 明白存储的是谁, 记忆化存储也可以用map, 本来觉得可以用dfs, 但是是求个数, 所以想到用
动归, 然后想到记忆化存储, 画图: 明白存的是target的个数, 后序遍历, dp[i] 就是从下面上来的个数.

动归: dp[i] = Uj=0 && i > nums[j] n sum(dp[i - dp[i - nums[j]]), 此处i不是遍历到第i个, 而是每次都应该遍历一遍
找到所有的状态 DP 解法: the key to solve DP problem is to think about how to create overlap,
how to re-solve subproblems(怎么制造复用)

 

暴力法
public int combinationSum4(int[] nums, int target) {
    if (target == 0) {
        return 1;
    }
    int res = 0;
    for (int i = 0; i < nums.length; i++) {
        if (target >= nums[i]) {
            res += combinationSum4(nums, target - nums[i]);
        }
    }
    return res;
}

暴力法转化为动归---top down---memory search:
private int[] dp;

public int combinationSum4(int[] nums, int target) {
    dp = new int[target + 1];
    Arrays.fill(dp, -1);
    dp[0] = 1;
    return helper(nums, target);
}

private int helper(int[] nums, int target) {
    if (dp[target] != -1) {
        return dp[target];           // 
    }
    int res = 0;
    for (int i = 0; i < nums.length; i++) {
        if (target >= nums[i]) {
            res += helper(nums, target - nums[i]);
        }
    }
    dp[target] = res;
    return res;
}

动归----bottom up
public int combinationSum4(int[] nums, int target) {
    int[] comb = new int[target + 1];
    comb[0] = 1;
    for (int i = 1; i < comb.length; i++) {
        for (int j = 0; j < nums.length; j++) {
            if (i - nums[j] >= 0) {
                comb[i] += comb[i - nums[j]];
            }
        }
    }
    return comb[target];
}

 错误的做法: 因为dp[j][i] != dp[j -1] + dp[j], 因为nums[j -1] 可能用多次, 不是只用一次, 这样就少写了情况, 看来不是维度越多越好, 只要找到一维, 按着这一个状态来递推就行, 一般是文中的题意变量作为状态, 不要老是想着遍历到第几个变量作为状态

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

 

Follow up:

I think if there are negative numbers in the array, we must add a requirement that each number is only used one time, or either positive number or negative number should be used only one time, otherwise there would be infinite possible combinations.
For example, we are given:
{1, -1}, target = 1,
it‘s obvious to see as long as we choose n 1s and (n-1) -1s, it always sums up to 1, n can be any value >= 1.

 

 

以上是关于377. Combination Sum IV的主要内容,如果未能解决你的问题,请参考以下文章

377. Combination Sum IV

算法: 求和377. Combination Sum IV

算法: 求和377. Combination Sum IV

377. Combination Sum IV

377. Combination Sum IV

377. Combination Sum IV