来自北大算法课的Leetcode题解:322. 零钱兑换

这篇博客探讨了如何使用动态规划方法解决寻找最小硬币组合的问题。作者提供了两种解法,一种是递归优化,另一种是标准动态规划方案。代码实现包括了两种解法,并针对超时问题进行了优化。文章还包含了对解法的详细解释和讨论。

代码仓库Github | Leetcode solutions @doubleZ0108 from Peking University.

  • 解法1(超时): 递归,自上而下,例如我有三种币值1 2 5,那么n的最少兑换次数 = min(1+n-1, 1+n-2, 1+n-5)

    • 改进(超时):加入memo,把之前算过的存起来
  • 解法2(T58% S61%): 动态规划,自下而上,把 1,2,…amount 每个面值需要的数量都算出来

    • 注意要判断当前coin的合法性(是不是比所需的amount小)
    this_count = 1+dp[i-count]
    min_count = min(min_count, this_count)
    
class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        if amount == 0: return 0
        if amount in coins: return 1
        if amount<min(coins): return -1

        INF = 1e06
        dp = [INF for _ in range(amount+1)]
        for c in coins:
            if c < amount: 
                dp[c] = 1

        for i in range(amount+1):
            if dp[i] == INF:
                for coin in [c for c in coins if c<=i]:
                    dp[i] = min(dp[i], 1+dp[i-coin])
        return dp[i] if dp[i]!=INF else -1

    
    # 一直超时 不保证正确
    def otherSolution(self, coins, amount):
        if len(coins) == 1:
            if amount % coins[0] == 0:
                return amount // coins[0]
            else:
                return -1

        # 解法1
        # 改进1
        min_table = [-1 for _ in range(amount)]
        def coinCount(coins, amount):
            if not coins:
                return -1
            if amount <= 0:
                return 0
            if amount in coins:
                return 1
            if min_table[amount-1] != -1:
                return min_table[amount-1]

            min_coin_change = -1
            for coin in coins:
                if coin == amount:
                    min_coin_change = 1
                    break
                elif coin > amount:
                    continue
                else:
                    this_change = coinCount([c for c in coins if c<=amount-coin], amount-coin)
                    if this_change >= 1:
                        if min_coin_change == -1:
                            min_coin_change = 1 + this_change
                        else:
                            min_coin_change = min(min_coin_change, this_change+1)

                        if min_table[amount-1] == -1:
                            min_table[amount-1] = 1+this_change
                        else:
                            min_table[amount-1] = min(min_table[amount-1], this_change+1)
            return min_coin_change

        return coinCount(coins, amount)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

doubleZ0108

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值