代码随想录第三十八天(一刷&&C语言)|零钱兑换II&&组合总数和 IV

创作目的:为了方便自己后续复习重点,以及养成写博客的习惯。

一、零钱兑换II

思路:参考carl文档

1、确定dp数组以及下标的含义:凑成总金额j的货币组合数为dp[j]。

2、确定递推公式:dp[j] 就是所有的dp[j - coins[i]]相加,递推公式为dp[j] += dp[j - coins[i]]。

3、dp数组如何初始化:dp[0] = 1理解为凑成总金额0的货币组合数为1,其余下标dp[j]初始化为0,这样累计加dp[j - coins[i]]时不会影响dp[j]。

4、确定遍历顺序:

 外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)(组合)

for (int i = 0; i < coins.size(); i++) {                     
    for (int j = coins[i]; j <= amount; j++) {             // 遍历背包
        dp[j] += dp[j - coins[i]];
    }
}

5、举例推导dp数组

ledcode题目:https://leetcode.cn/problems/coin-change-ii/description/

AC代码:

int change(int amount, int* coins, int coinsSize) {
    int dp[amount + 1];
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for (int i = 0; i < coinsSize; i++) {
        for (int j = coins[i]; j <= amount; j++) {
            dp[j] += dp[j - coins[i]];
        }
    }
    return dp[amount];
}

二、组合总数和 IV

思路:参考carl文档

1、确定dp数组以及下标的含义:凑成目标正整数为i的排列个数为dp[i]。

2、确定递推公式:dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导出来。

排列个数dp[i - nums[j]],是dp[i]的一部分。求装满背包有几种方法,递推公式一般都是dp[i] += dp[i - nums[j]]。

3、dp数组如何初始化:由递推公式dp[i] += dp[i - nums[j]]知dp[0]初始化为1,非0下标的dp[i]初始化为0,这样才不会影响dp[i]累加dp[i - nums[j]]。

4、确定遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历。(排列)

5、举例来推导dp数组

lecode题目:https://leetcode.cn/problems/combination-sum-iv/description/

AC代码:

int combinationSum4(int* nums, int numsSize, int target) {
    int dp[target + 1];
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for (int i = 1; i <= target; i++) {
        for (int j = 0; j < numsSize; j++) {
            if (nums[j] <= i && dp[i - nums[j]] < INT_MAX - dp[i]) {
                dp[i] += dp[i - nums[j]];
            }
        }
    }
    return dp[target];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值