题目

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

示例 1:

1
2
3
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1

示例 2:

1
2
输入:coins = [2], amount = 3
输出:-1

示例 3:

1
2
输入:coins = [1], amount = 0
输出:0

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

题解

同样的 DP 题,硬币的数量不用考虑,只需要考虑怎么选硬币就好了:

1)如果硬币的下标小于 0 了,如果此时 remaining 为 0,说明凑到了;否则凑不到;

2)如果剩余的钱数少于当前币值,就换一个小的硬币继续尝试;

2)不然就有两张情况可以选择:继续当前硬币或者换一个小的币值,这里的判断用硬币的个数去判断即可。

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
@cache
def dfs(i: int, remaining: int) -> int:
# 如果没有硬币合适了
if i < 0:
# 如果 remaining 也刚好为 0,说明凑好了
return 0 if remaining == 0 else inf
# 如果剩余的钱比当前硬币小,就换小一个的硬币
if remaining < coins[i]:
return dfs(i - 1, remaining)
# 不然的话,判断是继续用当前的硬币或者是用小一点的硬币
return min(dfs(i - 1, remaining), dfs(i, remaining - coins[i]) + 1)

# 和上一题一样还是使用 DFS 的一个思路
ans = dfs(len(coins) - 1, amount)
# 额外的处理,inf 的话,要用 -1 输出
return ans if ans < inf else -1

运行结果

image.png