题目描述
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
算法思路
动态规划
自底向上
这里第一个想到的是自底向上的动态规划。
动态转移方程:dp[i]=dp[i-coin]+1;coin是一个列表
# dp[i] 表示金额为i需要最少的硬币
# dp[i] = min(dp[i], dp[i - coins[j]]) j所有硬币
算法:
第一步:dp数组初始化
dp = [float("inf")] * (amount + 1)
dp[0] = 0
第二步:动态转移方程
for i in range(1, amount + 1):
dp[i] = min(dp[i - c] if i - c >= 0 else float("inf") for c in coins ) + 1
!条件表达式和推导式结合。
return dp[-1] if dp[-1] != float("inf") else -1
执行用时 :1084 ms, 在所有 Python3 提交中击败了90.63%的用户
内存消耗 :13.6 MB, 在所有 Python3 提交中击败了22.01%的用户
自顶向下
递归的动态规划
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
import functools
@functools.lru_cache(None)
def helper(amount):
if amount == 0:
return 0
return min(helper(amount - c) if amount - c >= 0 else float("inf") for c in coins) + 1
res = helper(amount)
return res if res != float("inf") else -1
——
解释:
import functools
@functools.lru_cache(None)
@functools.lru_cache(maxsize=128, typed=False)
一个为函数提供缓存功能的装饰器,缓存 maxsize 组传入参数,在下次以相同参数调用时直接返回上一次的结果。
广度优先搜索 BFS
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
# 两端队列,可以用列表代替
from collections import deque
queue = deque([amount])
step = 0
visited = set()
while queue:
n = len(queue)
for _ in range(n):
tmp = queue.pop()
if tmp == 0:
return step
# 对每一个金额,遍历减去每种硬币,所有可能结果保存在集合里
for coin in coins:
if tmp >= coin and tmp - coin not in visited
visited.add(tmp - coin)
queue.appendleft(tmp - coin)
step += 1
return -1
每一次都是遍历所有的硬币可能,然后硬币数量加一,当tmp==0;return step即是最少硬币数
深度优先搜索 DFS
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
coins.sort(reverse=True)
self.res = float("inf")
def dfs(i, num, amount):
if amount == 0:
self.res = min(self.res, num)
return
for j in range(i, len(coins)):
# 剩下的最大值都不够凑出来了
if (self.res - num) * coins[j] < amount:
break
if coins[j] > amount:
continue
dfs(j, num + 1, amount - coins[j])
for i in range(len(coins)):
dfs(i, 0, amount)
return self.res if self.res != float("inf") else -1
作者:powcai
链接:https://leetcode-cn.com/problems/coin-change/solution/dong-tai-gui-hua-bfs-dfs-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。