为了账号安全,请及时绑定邮箱和手机立即绑定

LeetCode 零钱兑换

标签:
Python 算法

零钱兑换


题目


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

示例 1:

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

示例 2:

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

说明:

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

解题思路


  1. 贪心算法 + DFS;
  2. 在本题当中,可以考虑先取最大面值的硬币(先对 coins 进行排序,由大到小),当取最大面值的硬币超出总额的时候,则取下一个稍微小的硬币;
  3. 当取硬币的时候,不一定要逐个取,用乘法代替加法。比如:times = amout // coins[index],这个式子就是计算最多可取多少个硬币。这里可能取到一种情况,就是由大到小取硬币的时候,可能前面的取的硬币导致后面无法凑出总额。遇到这种情况则考虑回溯减少前面取较大硬币的数量。
  4. 这里要考虑一些特殊的情况。coins = [1, 7, 10], amount = 14,按照上面的思路,这里优先得到的结果可能是 10, 1, 1, 1, 1,而不是最优的 7, 7,所以要将所有的情况递归完成。
  5. 上面的问题可以看出,贪心算法可能得到的不是最优解,但同样可以实现快速剪枝。

代码实现


class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        def coin_change(coins, amount, index, count, res):
            if amount == 0:
                return min(count, res)
            if index == len(coins):
                return res
            
            # 这里用乘法代替加法,直接获得最多可取值
            times = amount // coins[index]

            while times >= 0 and count + times < res:
                res = coin_change(coins, amount - times * coins[index], index + 1, count + times, res)
                times -= 1
            return res
        
        if amount == 0:
            return 0
        coins.sort(reverse=True)
        res = coin_change(coins, amount, 0, 0, float('inf'))
        return res if res != float('inf') else -1

实现结果


实现结果


以上就是使用贪心算法 + DFS 解决《零钱兑换》问题的主要内容。


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消