给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
方案:动态规划:自下而上
我们采用自下而上的方式进行思考。仍定义 为组成金额 所需最少的硬币数量,假设在计算 之前,我们已经计算出 的答案。 则 对应的转移方程应为:
其中 代表的是第 枚硬币的面值,即我们枚举最后一枚硬币面额是 ,那么需要从 这个金额的状态 转移过来,再算上枚举的这枚硬币数量 11 的贡献,由于要硬币数量最少,所以 为前面能转移过来的状态的最小值加上枚举的硬币数量 11 。
例子1:假设
coins = [1, 2, 5], amount = 11
则,当 时无法用硬币组成,为 0 。当 时,忽略
我们可以看到问题的答案是通过子问题的最优解得到的。
例子2:假设
coins = [1, 2, 3], amount = 6
在上图中,可以看到:
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [0] + [amount+1]*amount
for i in range(1, amount+1):
for c in coins:
if i >=c:
dp[i] = min(dp[i], dp[i-c]+1)
return dp[-1] if dp[-1] != amount+1 else -1