代码随想录第三十八天(一刷&&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/

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

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/

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

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];
}

你可能感兴趣的:(c语言,开发语言)