题目
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins = [2], amount = 3
输出:-1
示例 3:
输入:coins = [1], amount = 0
输出:0
题解
python
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
@cache
# 完全背包问题
# dfs(i, c) = 使用硬币种类 coins[0], coins[1], ..., coins[i]来凑出恰好金额c所需的最少硬币数量
# i:当前可以考虑的硬币种类的最大索引
# i = 0 表示只能使用第一种硬币 coins[0]
# i = 2 表示可以使用前三种硬币 coins[0], coins[1], coins[2]
# c:需要凑出的剩余目标金额
def dfs(i:int,c:int)->int:
# 没有硬币可用(i < 0),但金额也刚好为0,说明之前的硬币选择已经完美凑出了目标金额
if i < 0:
return 0 if c == 0 else inf
# 不选该硬币
if c < coins[i]:
return dfs(i-1,c)
# 不选 vs 选
# 这里覆盖了没有任何一种硬币组合能组成总金额的情况,此时这里会返回inf
return min(dfs(i-1,c),dfs(i,c-coins[i])+1)
ans = dfs(len(coins) - 1,amount)
return ans if ans<inf else -1
复杂度分析
- 时间复杂度:O(n⋅amount),其中 n 为 coins 的长度。
- 空间复杂度:O(n⋅amount)。