零钱兑换Ⅱ
518. 零钱兑换 II - 力扣(LeetCode)
给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。
示例 1:
输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:
输入:amount = 3, coins = [2]
输出:0
解释:只用面额 2 的硬币不能凑成总金额 3 。
示例 3:
输入:amount = 10, coins = [10]
输出:1
提示:
1 <= coins.length <= 300
1 <= coins[i] <= 5000
coins 中的所有值互不相同
0 <= amount <= 5000
解题思路
动态规划
完全背包问题的组合问题,即每个元素都可以重复利用,直到装满背包共有多少种组合
1.确定dp数组及下标的含义
dp[j] 表示 凑成总金额为 j 共有多少种组合
2.确定递推公式
若不考虑coins[i], 装满容量 j - coins[i]背包,有dp[ j - coins[i] ]种方法,
如果把coins[i]装入正好装满容量为j的背包,凑成dp[j]就有dp[ j - coins[i] ]种方法
故递推公式为**dp[j] += dp[ j - coins[i] ]**,表示加入了物品coins[i]之后dp[j]新增了多少种方法,即凑成总金额为 j 新增的方法
3.初始化dp数组
dp[0] = 1,背包容量为0有一种方法,表示什么都不放,该值必须初始化为1,否则无法递推下去
4.确定遍历顺序
本题求的是组合数,先遍历物品,再遍历背包,完全背包问题背包容量从小到大遍历
(如果是求排列数,就要先遍历背包,在遍历物品)
举例:
输入:amount=5,coins = {1,2,5}
dp数组的状态如图

代码
1 |
|
时间复杂度:$O(n × m)$,n为数组coins大小,m为amount
空间复杂度:$O(m)$