LeetCode 322. 零钱兑换 完全背包问题

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1

示例 1:

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

示例 2:

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

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

 

 

简单介绍一下背包问题:

背包问题

1. 01背包,选和不选的问题
2. 完全背包,选几个的问题(物品不限次数)->转化成背包问题解决(每次选还是不选,重复访问同一物品)
3. 多重背包,即每个物品有限个

思路1:动态规划

状态转移方程:

 状态:记录0-amount内,每种金额所需的最少硬币数
 f[amount]=min(f[amount],f[amount-coints[i]+1])   #f[amount-coints[i] 表示选取一个coin后,还剩的待凑的钱数

 

class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
#        1. 动态规划
# 记录0-amount内,每种金额所需的最少硬币数
# f[amount]=min(f[amount],f[amount-coints[i]]+1)
        dp=[float('inf')]*(amount+1)
        dp[0]=0
        for i in range(amount+1):
            for j in coins:
                if i>=j:
                    dp[i]=min(dp[i],dp[i-j]+1)
        if dp[-1]>amount:return -1
        else: return dp[-1]
        

法二:DFS   

先将硬币面额按照大小排序,从每个不同面额的硬币开始DFS

class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
# dfs(实质是可以重复访问的dfs过程) 优先选大面额的
        self.res=amount+1
        coins_len=len(coins)
        if coins_len==0:return -1
        if amount==0:return 0
        coins.sort(reverse=True)
        if amount<coins[-1]:return -1
        count=0
        # 从每个面额开始深搜
        for i in range(coins_len):
            self.dfs(coins,i,amount,count)
        if self.res!=amount+1:return self.res
        else:return -1
        
       
        
    def dfs(self,coins,coins_index,amount,count):
        # dfs过程
        if amount==0:
            self.res=min(self.res,count)
            return
        for i in range(coins_index,len(coins)):
            # 继续dfs条件
            if coins[i]<=amount<(self.res-count)*coins[i]:
                self.dfs(coins,i,amount-coins[i],count+1)
        

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值