You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

Example 1:

Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:

Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

这又是一道动态规划的题目,动态规划其实就是一种穷举的方式,只是看如何的聪明的穷举

我们首先看到一个规律 即coin的凑法 f(coin) = f(coin - 1) + 1. 相当于金钱的凑法相当于 金钱-1个金钱凑法 再加上一枚金钱(可以是1,2,5)所以我们的状态方程是

 

F(coins) = F(coins - 1) + 1  其中F(coins) 返回的是金钱的凑的次数、

那么我们找到最少的金钱凑的次数 方程为 min(F(coins)) = min(F(coins - 1) + 1)

下面是动态规划的base 即如果剩下的钱为0 则证明正好凑齐 返回0 如果剩下的钱是-1 则说明凑钱失败 返回-1

下面是程序的模板

# 伪码框架
def coinChange(coins: List[int], amount: int):
 
# 定义:要凑出金额 n,至少要 dp(n) 个硬币
def dp(n):
# 做选择,选择需要硬币最少的那个结果
for coin in coins:
res = min(res, 1 + dp(n - coin))
return res
 
# 题目要求的最终结果是 dp(amount)
return dp(amount)

下面是程序:

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        meno = dict()
        def dp(n):
            if(n == 0): return 0
            if(n < 0): return -1
            if n in meno: return meno[n]
            res = float('INF')                     #设定与一个MAX value
            for coin in coins:
                subroutine = dp(n-coin)            #求出F(coins) = F(coins - 1) + 1 的状态方程
                if(subroutine == -1): continue
                
                res = min(res, subroutine + 1)
            meno[n] = res                           #这个是dp table用来剪裁不必要的分支
            if res != float('INF'):
                return meno[n]
            else:
                return -1
        return dp(amount)

 

 

动态规划的总结:

1. 找出F(n)和F(n-1) 之间的区别。

2. 找出base 的条件

3. 利用dp table去消除重复的分支项。

posted on 2020-06-16 06:28  闲云潭影  阅读(75)  评论(0编辑  收藏  举报