leetcode-zgd-day44-518.零钱兑换II/377.组合总和IV

131 阅读2分钟

518.零钱兑换II

题目链接:518. 零钱兑换 II - 力扣(LeetCode)

解题思路:

这个题目是完全背包的第一个应用题。主要的关注点在于01背包和完全背包的区别把:

1.循环的内外层是否可以交换

二维dp数组的01背包和完全背包都是可以交换内外层循环的,背包容量在外也行,物品在外也行

一维dp数组的01背包不可以交换内外层循环,一定是物品在外,容量在内,因为内层循环需要逆向遍历。

一维dp数组的完全背包问题可以交换内外层循环的顺序,因为内层容量的循环要正向遍历。用到的都是前面的值,前面的值肯定都已经有递推结果了。

2.循环的遍历方向

1维dp数组的01背包内层容量遍历必须是从后向前的

1维dp数组的完全背包内层背包容量遍历必须是从前向后的

但是本题虽然是完全背包的一个应用题,但是并不能交换内外层循环的顺序,因为本题像要求的是有多少种符合要求的组合数,这个结果是不需要考虑元素顺序的。

将物品循环放在外层,求出的结果就是排列的种类总数,而不是组合的种类总数。

 class Solution {
     public int change(int amount, int[] coins) {
         /**
          * 该题目不是01背包问题了,因为物品可以无限量的取。所以是完全背包问题
          * 1.dp[j]  总结j一共有多少种凑的方案
          * 2.dp[j] = Math.max(dp[j], dp[j - coins[i]]);
          * 3.dp[0] = 1;
          */
         int[] dp = new int[amount + 1];
         dp[0] = 1;
         for(int i = 0; i < coins.length; i++){
             for(int j = coins[i]; j <= amount; j++){
                 dp[j] += dp[j - coins[i]];
             }
         }
         return dp[amount];
     }
 }

377.组合总和IV

题目链接:377. 组合总和 Ⅳ - 力扣(LeetCode)

解题思路:

这个题就是完全背包问题中的排列总和问题。

 class Solution {
     public int combinationSum4(int[] nums, int target) {
         /**
          * 该题目是完全背包问题中的排列总数问题,直接确定背包容量在外层,物品在内层
          * 1.dp[j] 组成j有多少种排列
          * 2.dp[j] = dp[j] + dp[j - nums[i]]
          * 3.dp[0] = 1;
          * 4.内外层正向循环,外层容量 内层物品
          */
         int[] dp = new int[target + 1];
         dp[0] = 1;
         for(int j = 0; j <= target; j++){
             for(int i = 0; i < nums.length; i++){
                 if(j >= nums[i]) dp[j] += dp[j - nums[i]];
             }
         }
         return dp[target];
     }
 }