377. 组合总和 Ⅳ(dp)

 

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

 

示例 1:

输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。

示例 2:

输入:nums = [9], target = 3
输出:0

 

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 1000
  • nums 中的所有元素 互不相同
  • 1 <= target <= 1000

 

进阶:如果给定的数组中含有负数会发生什么?问题会产生何种变化?如果允许负数出现,需要向题目中添加哪些限制条件?

 

 

class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:
        n = len(nums)
        dp = [0] * (target+1)
        dp[0] = 1
        for i in range(target+1):
            for j in range(len(nums)):
                if i - nums[j]>=0:
                    dp[i] += dp[i-nums[j]]
        return dp[target]

 

 

 超时

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        if (target==0) {
            return 1;
        }
        int res = 0;
        for (auto num : nums) {
            if (target-num>=0) {
                res += combinationSum4(nums,target-num);
            }
        }
        return res;
    }
};

备忘录

class Solution {
public:
    int help(vector<int>& nums, int target,vector<int>& memo) {
        if (memo[target]!=-1) return memo[target];
        
        if (target==0) {
            return 1;
        }
        int res = 0;
        for (auto num : nums) {
            if (target-num>=0) {
                res += help(nums,target-num,memo);
            }
        }
        memo[target] = res;
        return res;
    }
    int combinationSum4(vector<int>& nums, int target) {
        vector<int> dp = vector<int>(target+1,-1);
        dp[0] = 1;
        int res = help(nums,target,dp);
        return res;
    }
};

 

 dp

    int combinationSum4(vector<int>& nums, int target) {
        vector<unsigned int> dp = vector<unsigned int>(target+1,0);
        dp[0] = 1;
        for(int i = 1; i <= target;i++) {
            for(auto num : nums) {
                if (i-num>=0) {
                    dp[i] += dp[i-num];
                }
            }
        }
        return dp[target];
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本题与「完全背包求方案数」问题的差别在于:选择方案中的不同的物品顺序代表不同方案。

举个 🌰,在「完全背包」问题中,凑成总价值为 6 的方案 [1,2,3] 算是 11 种方案,但在本题算是 3 * 2 * 1 = 63∗2∗1=6 种方案([1,2,3],[2,1,3],[3,1,2] ... )。

 

 

 

 

 

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        int len = target;
        vector<vector<unsigned long long >> dp (len+1,vector<unsigned long long>(target+1,0));
        dp[0][0] = 1;
        for (int i = 1;i <= len;++i) {
            for(int j =0;j <=target;j++) {
                for (int x : nums) {
                    if (j-x>=0) {
                        dp[i][j] += dp[i-1][j-x];
                    }
                }
            }
        }
        int sum = 0;
        for (int k =0;k <=target;k++) {
            sum +=dp[k][target];
        }
        return sum;
    }
};

 

 

posted @ 2021-11-04 09:23  乐乐章  阅读(27)  评论(0编辑  收藏  举报