【算法与数据结构】518、LeetCode零钱兑换 II

本文详细介绍了如何使用动态规划解决LeetCode中的完全背包问题,通过抽象为物品和背包容量的组合问题,给出了递归公式并分析了时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解

一、题目

在这里插入图片描述

二、解法

  思路分析:本题的硬币是无数的,因此本题可以抽象成一个完全背包问题。完全背包和01背包的不同之处在于完全背包式从前往后遍历的。在本题的完全背包问题中,amount代表背包的最大重量,coins数组代表物品的重量和价值。 d p [ i ] dp[i] dp[i]代表背包重量为 i i i时,硬币凑成的组合(2 2 1 和 2 1 2这两个是不同排列,但是它们属于一个组合)总数为 d p [ i ] dp[i] dp[i]。我们将 d p [ 0 ] dp[0] dp[0]初始化为1,不需要找零也是一种组合。 d p [ j ] dp[j] dp[j]可以由 d p [ j − c o i n s [ i ] ] dp[j - coins[i]] dp[jcoins[i]]得出。因为求的是组合总数,所以递归公式为: d p [ j ] + = d p [ j − c o i n s [ i ] ] dp[j] += dp[j - coins[i]] dp[j]+=dp[jcoins[i]]特别需要注意的是,因为题目要求的是组合数而不是排列数,所以本题循环采取的是先遍历物品,后遍历背包容量的形式。如果说题目要求的是排列数,例如【算法与数据结构】377、LeetCode组合总和 Ⅳ这道题要求的就是排列数,遍历顺序则需要用先遍历背包容量,后遍历物品的方式,保证每个背包容量所有的排列数都被遍历到。
  程序如下

class Solution {
public:
	int change(int amount, vector<int>& coins) {
		vector<int>dp(amount + 1, 0);
		dp[0] = 1;
		// 先遍历物品,再遍历背包
		for (int i = 0; i < coins.size(); i++) { // 遍历物品
			for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
				dp[j] += dp[j - coins[i]];
			}
		}
		return dp[amount];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm), n=amount,m是coin数组的大小。
  • 空间复杂度: O ( n ) O(n) O(n)

三、完整代码

# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;

class Solution {
public:
	int change(int amount, vector<int>& coins) {
		vector<int>dp(amount + 1, 0);
		dp[0] = 1;
		// 先遍历物品,再遍历背包
		for (int i = 0; i < coins.size(); i++) { // 遍历物品
			for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
				dp[j] += dp[j - coins[i]];
			}
		}
		return dp[amount];
	}
};

int main() {
	Solution s1;
	int amount = 5;
	vector<int> coins = { 1, 2, 5 };
	int result = s1.change(amount, coins);
	cout << result << endl;
	system("pause");
	return 0;
}

end

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晚安66

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

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

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

打赏作者

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

抵扣说明:

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

余额充值