题目
给定不同面额的硬币 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_cache
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
if amount == 0:
return 0
min_coins = min(coins)
# 使用一个函数而不是直接使用递归是为了只执行一次 min(coins)
@lru_cache(maxsize=None)
def getMin(amount: int) -> int:
# 获取组成 amount 的最小硬币数
if amount < min_coins:
return -1
if 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 -1
else:
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] = 0
for 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/