给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
示例 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来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change-2
方法1: 动态规划
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
coin_len=len(coins)
dp=[ [0 for _ in range(amount+1)] for _ in range(coin_len+1) ]
for i in range(coin_len+1):
dp[i][0]=1
# 扫描全部coins和amount的组合
for i in range(1,coin_len+1):
for j in range(1,amount+1):
# 如果你不把这第 i 个物品装入背包,也就是说你不使用 coins[i] 这个面值的硬币,
# 那么凑出面额 j 的方法数 dp[i][j] 应该等于 dp[i-1][j],继承之前的结果。
# 如果你把这第 i 个物品装入了背包,也就是说你使用 coins[i] 这个面值的硬币,那
# 么 dp[i][j] 应该等于 dp[i][j-coins[i-1]]
#
if j-coins[i-1]>=0:
dp[i][j]=dp[i-1][j]+dp[i][j-coins[i-1]]
else:
dp[i][j]=dp[i-1][j]
return dp[coin_len][amount]
方法2:缩两维数组为1维数组
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
coin_len=len(coins)
# 压缩两维数组为1维数组
dp=[0 for _ in range(amount+1)]
dp[0]=1
for i in range(0,coin_len):
for j in range(1,amount+1):
if (j-coins[i-1])>=0:
dp[j]=dp[j]+dp[j-coins[i-1]]
return dp[amount]
方法3:
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
coin_len=len(coins)
# 特殊条件判断
if amount == 0:
return 1
# 根据Python特性重新构建新的迭代关系,并修改原有的状态转移公式
dp = [0] * (amount + 1)
dp[0] = 1
for coin in coins:
for i in range(coin, amount + 1):
dp[i] = dp[i] + dp[i - coin]
return dp[amount]