📅  最后修改于: 2023-12-03 15:11:24.032000             🧑  作者: Mango
硬币变化问题是一个经典的动态规划问题,目标是确定给定面额硬币的组合方式,使其总价值恰好等于给定值。
给定一组面值为 $coins$ 的硬币和一个目标值 $amount$,编写一个函数来计算可以用给定的硬币组成的面值总和是否等于 $amount$。可以假设每个硬币都可以无限次被使用。
输入:$coins = [1, 2, 5], amount = 11$
输出:3 (使用 $5, 5, 1$ 硬币)
这是一个典型的动态规划问题,需要用到动态规划的思想和技巧:
确定状态:设 $dp[i]$ 为凑出面值 $i$ 所需的最小硬币数,初始化为 $dp[0]=0$,其他值初始化为一个特殊的值,比如 -1 或正无穷。
状态转移:对于每个面值 $i$,需要遍历每一种硬币 $coins_j$,找到凑出 $i-coins_j$ 的最小硬币数,并将其加上 1,即可得到 $dp[i]$ 的值。注意需要判断 $i-coins_j$ 是否越界。
返回结果:如果 $dp[amount]$ 的值不为特殊值,说明可以用给定的硬币组合成 $amount$ 的面值,返回其值;否则返回 -1。
def coinChange(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for j in range(len(coins)):
if coins[j] <= i:
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
本算法的时间复杂度为 $O(N^2)$,其中 $N$ 是目标值 $amount$ 的大小。算法的主要时间耗费在双重循环中,而循环次数最多为 $amount$ 的平方。
本算法的空间复杂度为 $O(N)$,用一个长度为 $N+1$ 的数组存储了所有状态矩阵。