题目
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:**
from functools import lru_cacheclass Solution:def coinChange(self, coins: List[int], amount: int) -> int:if amount == 0:return 0min_coins = min(coins)# 使用一个函数而不是直接使用递归是为了只执行一次 min(coins)@lru_cache(maxsize=None)def getMin(amount: int) -> int:# 获取组成 amount 的最小硬币数if amount < min_coins:return -1if amount in coins:return 1_min = []for coin in coins:if amount > coin:tmp = getMin(amount - coin)if tmp != -1: # 可以凑成满足条件金额_min.append(tmp + 1)if not _min:return -1else:return min(_min)return getMin(amount)
方案二(动态规划,完全背包问题)
class Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 转换成背包问题:# 将总金额看做是背包大小,则只需要求出填满背包的最少的硬币数量即可dp = [float('inf')] * (amount + 1) # dp[i] 表示填满背包大小为 i 所需的硬币的最小数量dp[0] = 0for coin in coins:for i in range(coin, amount + 1):dp[i] = min(dp[i], 1 + dp[i - coin])return dp[-1] if dp[-1] != float('inf') else -1
- 参考完全背包问题解法。
参考链接
https://leetcode-cn.com/problems/coin-change/
