今天的每日一练很没意思,就不说了
主要是来复习一遍昨天的 322. 零钱兑换
用dfs和bfs来解决:
首先是非递归的bfs:
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
#简单bfs
if amount==0:return 0
from collections import deque
visited = set()
queue = deque([amount])
step =0
while queue:
n = len(queue)
for _ in range(n):
root = queue.popleft()
for coin in coins:
if root-coin==0:
return step+1
if root-coin>0 and root-coin not in visited:
visited.add(root-coin)
queue.append(root-coin)
step+=1
return -1
这道题特别适合bfs,如果要用dfs的话,最好用备忘录比较或者记下当前最小step.而用带备忘录的递归解法就是dp
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
#简单bfs
self.res = inf
def dfs(i,num,amount):
if amount==0:
self.res = num
return
for j in range(i,len(coins)):
# if (self.res - num)*coins[j]
if coins[j]<=amount and self.res>num+1:
dfs(j,num+1,amount-coins[j])
for i in range(len(coins)):
dfs(i,0,amount)
return self.res if self.res!= inf else -1
第一版dfs剪枝失败,超时了。。。
然后通过加上一点贪心的思想,将加载硬币的顺序倒置, 从最大的值开始记录,由于硬币顺序不是正序,还要先排队。
结果还是超时了,放弃。。。。究其原因,是剪枝完后的dfs还是会重复计算。一般能用dfs解的方法都可以用dp去掉一部分重复解。
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