动态规划-零钱兑换

问题描述

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

链接:https://leetcode-cn.com/problems/coin-change/

思路

使用动态规划解题。首先创建一个一维数组dp,dp[i]表示amount=i时的最少硬币数。通过dp[i]与dp[j]之间的关系递推出dp[i],其中 j<i。

递推公式

对于amount=i来说,其中找零面值可能是coins中的任何一种面值。我们假设找零面值中有一张面值为c的钱,那么我们很容易就会看出dp[i] = dp[i-c] + 1。
结合题目条件我们可以得出:
d p [ i ] = m i n ( [   d p [ i c ]   f o r   c   i n   c o i n s ]   ) + 1 dp[i] = min([\ dp[i-c]\ for \ c\ in\ coins]\ )+1
当然,想要满足以上递推公式需要一些限制条件:

  • i >= c
  • dp[i-c]必须有解

代码实现

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        if coins == [0]: # 特殊情况处理,该种情况下i-c=i,而i还未计算出来,初始时dp[i]=0,此时结果将会是1,但是是错误结果。
            return -1
        dp = [0] * (amount + 1) 
        for i in range(1,amount + 1):
            min = amount # min为dp[i-c]的最小值,初始化为amount
            for c in coins: # 寻找最小的dp[i-c]
                min = dp[i-c] if i>=c and dp[i-c]!=-1 and dp[i-c]<min else min
            dp[i] = min+1 if min!=amount else -1 # min=amount说明没有最小dp[i-c],即为无解
        return dp[-1]
发布了2 篇原创文章 · 获赞 1 · 访问量 32

猜你喜欢

转载自blog.csdn.net/weixin_44510898/article/details/105262470