当前位置:   article > 正文

LeetCode:322. 零钱兑换(python)_leetcode 322 python

leetcode 322 python
LeetCode:322. 零钱兑换(python)

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

示例 1:

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

示例 2:

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

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

LeetCode 链接


思路:
  1. 递归(超时),递归遍历添加所有硬币的情况,每次添加某硬币,则递归遍历总金额-某硬币 的子问题。

    • 当前总金额'0 则表明当前硬币情况有解,返回 0

    • 当前总金额' 不为 0,则继续添加硬币

      • 当前总金额'-硬币<0 表明不能添加该硬币(无解),尝试添加其他硬币。

      • 当前总金额'-硬币>0递归遍历 当前总金额-硬币 的子问题,若子问题无解,尝试添加其他硬币;若子问题有解,则每次添加硬币时记录,硬币数 +1,最终比较取最小值。

    • 返回情况,若子问题有解,则返回子问题的 最少硬币数,否则返回 -1

  2. 记忆递归,以上递归所有硬币情况存在大量重复,添加记忆字典 {当前总金额:值}进行剪枝,值为 -1 表明,当前总金额的情况无解,否则值为当前总金额需要的最少硬币数。

  3. 动态规划

    • 状态:金额 0 至金额 amountdp 数组记录当前金额的最少硬币数。
    • 选择当前金额 下是否添加 该硬币(遍历所有种类硬币情况),取决于所需硬币数的多少,若不添加则维持原硬币数;若添加则更新为 dp[当前金额-该硬币]+1
    • 初始值
      • dp 数组维度为 1×(amount+1),代表金额状态 0~amount;值为无穷大,方便比较最小值(所需硬币数最少)
      • dp[0]=0,表示金额为 0 时,所需硬币数为 0
    • 返回值:判断 dp[amout]
      • 若为无穷大,则表明该金额无法用所给的硬币种类求解;
      • 否则返回 amount 金额下所需的最少硬币数 dp[amount]
附代码1(Python3):递归(超时)
class Solution(object):
    def coinChange(self, coins, amount):
        if amount == 0:                                     # amount 为 0 表示当前硬币情况有解,则返回 0
            return 0
        res = float('inf')
        for coin in coins:
            if amount-coin < 0:                             # 若添加该硬币无解则尝试其他硬币
                continue
            sub_count = self.coinChange(coins, amount-coin) # 递归遍历子问题
            if sub_count == -1:                             # 若子问题无解则尝试其他硬币
                continue
            res = min(res, sub_count+1)                     # 子问题有解,硬币数加 1,取最小值
        return res if res!=float('inf') else -1             # 子问题有解则返回 res 值,无解则返回 -1  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
test = Solution()
coins_li = [[1,2,5],
            [2]
           ]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
    print(test.coinChange(coins, amount))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3
-1
  • 1
  • 2
附代码2(Python3):记忆递归
class Solution(object):
    def coinChange(self, coins, amount):
        memo = {}              # 记忆
        return self.recurve(coins, amount, memo)
    
    def recurve(self, coins, amount, memo):
        if amount == 0:
            return 0
        if amount in memo:
            return memo[amount]        

        res = float('inf')
        for coin in coins:
            if amount-coin < 0:
                continue
            sub_count = self.recurve(coins, amount-coin, memo)
            if sub_count == -1:
                continue
            res = min(res, sub_count+1)
        if res != float('inf'):
            memo[amount] = res
            return memo[amount]
        else:
            memo[amount] = -1
            return memo[amount]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
test = Solution()
coins_li = [[1,2,5],
            [2]
           ]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
    print(test.coinChange(coins, amount))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3
-1
  • 1
  • 2
附代码3(Python3):动态规划
class Solution(object):
    def coinChange(self, coins, amount):
        dp = [float('inf')]*(amount+1)
        dp[0] = 0
        for i in range(1, amount+1):
            for coin in coins:
                if coin <= i:
                    dp[i] = min(dp[i], dp[i-coin]+1)
        if dp[amount] == float('inf'):               # 该金额无解,则返回 -1
            return -1
        else:
            return dp[amount]                       # 该金额有解,则返回最少硬币数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
test = Solution()
coins_li = [[1,2,5],
            [2]
           ]
amount_li = [11, 3]
for coins, amount in zip(coins_li, amount_li):
    print(test.coinChange(coins, amount))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3
-1
  • 1
  • 2
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号