Day 43 | 完全背包| 518. 零钱兑换 II | 377. 组合总和 Ⅳ

完全背包

与01背包唯一不同的一点在于每件物品有无限个

在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序是无所谓的!

因为物品可以重复加,所以for循环嵌套顺序无所谓

之前倒叙是因为物品不能随便加

两层for可以颠倒

遍历背包的是列的方向,列项更新

遍历物品的是行的方向,横向更新

● 518. 零钱兑换 II

1.dp[j]:凑成总金额j的货币组合数为dp[j]

2.确定递归公式

dp[j] += dp[j-coins[i]];

3.初始化

dp[0] = 1是递归公式的基础

dp[0]的解释为凑成总金额0的货币组合数为0 / 1。题目中是默认了1的

dp[0] =1 说明如果正好选了coins[i]后,也就是j - coins[i] == 0 的情况表示这个硬币正好能选,dp[0] = 1表示只选coins[i]存在这样的一种选法。

4.确定遍历顺序

遍历顺序中dp[j]里计算的是组合数!

class Solution {
    public int change(int amount, int[] coins) {
    int[] dp = new int[amount+1];
    //初始化dp数组,金额为0的时候只有一种情况
    dp[0] = 1;
    for(int i = 0;i 
  

● 377. 组合总和 Ⅳ

class Solution {
    public int combinationSum4(int[] nums, int target) {
    int[] dp = new int[target+1];
    dp[0] = 1;
    for(int i = 0;i<=target;i++){
        for(int j = 0;j= nums[j]){
                dp[i] += dp[i-nums[j]];
            }
        }
    }
    return dp[target];
    }
}

以下是解决排列组合问题的背包算法的代码解析:

  • 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。

  • 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。

  • 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包

  • 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包

  • 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包

public class CombinationSum {
    public int combinationSum(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int i = 1; i <= target; i++) {
            for (int num : nums) {
                if (i - num >= 0) {
                    dp[i] += dp[i - num];
                }
            }
        }
        return dp[target];
    }
}
  1. int[] dp = new int[target + 1]; - 声明一个大小为target+1的数组dp,用于存储动态规划中的状态结果。初始值都为0。

  2. dp[0] = 1; - 将dp数组中索引为0的元素赋值为1。这是因为对于目标值为0时,只有一种方法,即不选择任何元素。

  3. for (int i = 1; i <= target; i++) { - 外层循环遍历目标值,从1开始直到target。

  4. for (int num : nums) { - 内层循环遍历数组nums中的每个元素。

  5. if (i - num >= 0) { - 判断当前目标值减去当前数组元素的差值是否大于等于0。如果小于0,则无法通过选择当前元素达到目标值。

  6. dp[i] += dp[i - num]; - 更新dp[i]的值,将dp[i-num](目标值为i-num时的方法数)累加到dp[i]上。这里的动态规划转移方程为dp[i] += dp[i - num],表示当目标值为i时,选择当前元素num的方法数等于目标值为i-num时的方法数。

  7. return dp[target]; - 返回dp数组中索引为target的元素,表示目标值为target时的方法数。该值即为问题的解。

该代码实现了一种背包算法解决排列组合问题的思路,通过动态规划的方式递推计算出目标值为target时的方法数。其中,外层循环遍历目标值,内层循环遍历数组元素,并根据动态规划转移方程更新dp数组的值。最后返回dp数组中索引为target的元素作为问题的解。

你可能感兴趣的:(算法,leetcode,动态规划)