代码随想录算法训练营Day44 || ● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ

今天接触了完全背包,即物品个数不做限制,只有背包容量的限制。对于完全背包这类问题,在进行遍历时可以不用考虑顺序,不过在求集合时有顺序之分。

问题1:518. 零钱兑换 II - 力扣(LeetCode)

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

思路:这里求的是组合数,dp[j]的含义是背包容量为j时的硬币组合数,应先对物品进行递归,再递归包,这样的话就避免了硬币顺序所造成的排列。代码如下:

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1,0);
        dp[0]=1;
        for(int i=0;i<coins.size();i++){
            for(int j=coins[i];j<=amount;j++){
                dp[j]+=dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

问题2:377. 组合总和 Ⅳ - 力扣(LeetCode)

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

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

思路:该题求的则是排列数,先遍历书包再遍历硬币,代码如下:

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<int> dp(target+1,0);
        dp[0]=1;
        for(int j=1;j<=target;j++){
            for(int i=0;i<nums.size();i++){
                if(j >= nums[i] && dp[j] <= INT_MAX-dp[j-nums[i]])  dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[target];
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_56969073/article/details/132483290
今日推荐