7月17号:完全背包问题例题,322. 零钱兑换:DP,DFS,BFS

本文详细探讨了322.零钱兑换问题的解决方案,包括使用广度优先搜索(BFS)进行非递归求解的方法,以及深度优先搜索(DFS)的不同实现方式。通过对这些方法的分析和对比,为读者提供了深入理解该问题的有效途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天的每日一练很没意思,就不说了

主要是来复习一遍昨天的 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

		
		
			
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值