【dp】排列问题——零钱兑换和组合总和IV

文章介绍了如何使用完全背包算法解决零钱兑换问题,区分了组合数与排列数在解题中的应用。对于组合数问题,采用先物品后容量的遍历方式;而对于排列数问题,需先容量后物品。动态规划的dp数组用于记录不同容量下的组合或排列计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

零钱兑换

在这里插入图片描述

很明显,本题使用完全背包算法,求解的是组合数,直接使用完全背包算法即可,为什么是组合数呢?

如果题目说 amount=5,coins=[1,2,5] 有9种方法,那就是排列数(挑选的元素有先后顺序),如下:

5=5
5=1+2+2
5=2+1+2
5=2+2+1
5=2+1+1+1
5=1+2+1+1
5=1+1+2+1
5=1+1+1+2
5=1+1+1+1+1
class Solution {
public:
    int change(int amount, vector<int>& coins) {
        int m = coins.size();
        int n = amount;
        vector<int> dp(n + 1, 0);  // dp[i]:容量为i的背包装满,最多有dp[i]种装法
        dp[0] = 1;
        // 组合:先物品、后容量
        // 遍历物品
        for(int i = 0; i < m; i++){
            // 完全背包:顺序遍历容量
            for(int j = coins[i]; j <= n; j++){
                dp[j] = dp[j] + dp[j - coins[i]];
            }
        }
        return dp[n];
    }
};

组合总和IV

在这里插入图片描述

题目有强调:顺序不同的序列被视作不同的组合

即我们本题求解是排列数

dp[i]: 使用数组nums,凑成整数 i 的排列个数

dp[i] = dp[i-nums[0]] + dp[i-nums[1]] + dp[i-nums[2]] + …

举个例子比如nums = [1,2,3],target = 4

dp[4] = dp[4-1] + dp[4-2] + dp[4-3] = dp[3] + dp[2] + dp[1]

其实就是说4的排列数可以由三部分组成:1和dp[3]、2和dp[2]、3和dp[1]

再比如nums = [2,3,4],target = 7

dp[7] = dp[7-2] + dp[7-3] + dp[7-4] = dp[5] + dp[4] + dp[3]

其实就是说4的排列数可以由三部分组成:2和dp[5]、3和dp[4]、4和dp[3]

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        // 完全背包
        // 排列:先容量、后物品
        int m = nums.size();
        int n = target;
        vector<int> dp(n + 1, 0);
        dp[0] = 1;
        for(int j = 1; j <= n; j++){
			for(int i = 0; i < m; i++){
				// 每一个小于当前容量j的物品nums[i],都会被当作第一个元素
				if(nums[i] <= j) dp[j] += dp[j - nums[i]];  
			}
		}
        return dp[n];
    }
};

为什么不能先遍历物品,后遍历容量呢?

如果先遍历物品,后遍历容量的话,举一个例子:计算dp[3]的时候,结果集只有 {1,2} 这样的集合,不会有{2,1}这样的集合,因为nums遍历放在外层,3只能出现在1后面!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值