赞
踩
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:你可以认为每种硬币的数量是无限的。
递归(超时),递归遍历添加所有硬币的情况,每次添加某硬币
,则递归遍历总金额-某硬币
的子问题。
若 当前总金额'
为 0
则表明当前硬币情况有解,返回 0
。
若 当前总金额'
不为 0
,则继续添加硬币
若 当前总金额'-硬币<0
表明不能添加该硬币(无解),尝试添加其他硬币。
若 当前总金额'-硬币>0
则递归遍历 当前总金额-硬币
的子问题,若子问题无解,尝试添加其他硬币;若子问题有解,则每次添加硬币时记录,硬币数 +1
,最终比较取最小值。
返回情况,若子问题有解,则返回子问题的 最少硬币数
,否则返回 -1
。
记忆递归,以上递归所有硬币情况存在大量重复,添加记忆字典 {当前总金额:值}
进行剪枝,值为 -1
表明,当前总金额的情况无解,否则值为当前总金额需要的最少硬币数。
动态规划
0
至金额 amount
,dp
数组记录当前金额的最少硬币数。当前金额
下是否添加 该硬币
(遍历所有种类硬币情况),取决于所需硬币数的多少,若不添加则维持原硬币数;若添加则更新为 dp[当前金额-该硬币]+1
。dp
数组维度为 1×(amount+1)
,代表金额状态 0~amount
;值为无穷大,方便比较最小值(所需硬币数最少)dp[0]=0
,表示金额为 0
时,所需硬币数为 0
。dp[amout]
amount
金额下所需的最少硬币数 dp[amount]
。class Solution(object):
def coinChange(self, coins, amount):
if amount == 0: # amount 为 0 表示当前硬币情况有解,则返回 0
return 0
res = float('inf')
for coin in coins:
if amount-coin < 0: # 若添加该硬币无解则尝试其他硬币
continue
sub_count = self.coinChange(coins, amount-coin) # 递归遍历子问题
if sub_count == -1: # 若子问题无解则尝试其他硬币
continue
res = min(res, sub_count+1) # 子问题有解,硬币数加 1,取最小值
return res if res!=float('inf') else -1 # 子问题有解则返回 res 值,无解则返回 -1
test = Solution()
coins_li = [[1,2,5],
[2]
]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
print(test.coinChange(coins, amount))
3
-1
class Solution(object): def coinChange(self, coins, amount): memo = {} # 记忆 return self.recurve(coins, amount, memo) def recurve(self, coins, amount, memo): if amount == 0: return 0 if amount in memo: return memo[amount] res = float('inf') for coin in coins: if amount-coin < 0: continue sub_count = self.recurve(coins, amount-coin, memo) if sub_count == -1: continue res = min(res, sub_count+1) if res != float('inf'): memo[amount] = res return memo[amount] else: memo[amount] = -1 return memo[amount]
test = Solution()
coins_li = [[1,2,5],
[2]
]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
print(test.coinChange(coins, amount))
3
-1
class Solution(object):
def coinChange(self, coins, amount):
dp = [float('inf')]*(amount+1)
dp[0] = 0
for i in range(1, amount+1):
for coin in coins:
if coin <= i:
dp[i] = min(dp[i], dp[i-coin]+1)
if dp[amount] == float('inf'): # 该金额无解,则返回 -1
return -1
else:
return dp[amount] # 该金额有解,则返回最少硬币数
test = Solution()
coins_li = [[1,2,5],
[2]
]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
print(test.coinChange(coins, amount))
3
-1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。