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

 

 

你可能感兴趣的:(leetcode,动态规划,回溯法)