力扣322.零钱兑换

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

示例 1:

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


示例 2:

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

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

 

题目连接:https://leetcode-cn.com/problems/coin-change/

方法一:递归实现

思路:见到可以将大问题划分为更小规模的问题,那么就可以想到用动态规划的方法。就像这道题,首先我们知道amount规模的问题,可以变成amount-coins[i]规模的问题,那么问题来了,amount规模的问题与amount-coins[i]规模的问题之间的关系是什么,递归结束条件是什么(也就是说已知的边界值是什么?)?然后将这个思路写成递归方程和递归结束条件,之后将其转换成代码。由于递归会超时,所以要用字典保存计算的中间结果。

$$ f(amount)=\left\{ \begin{aligned} 0, amount = 0 \\ 1+min{f(amount-coins[i])]}(i=0, 1,...,len(coins)-1), amount != 0 \end{aligned} \right. $$

注意:如果amount-coins[i]<0时,不符合题意,所以需要判断一下满足amount>=coins[i]才能递归。

class Solution:
    def coinC(self, amount):
        if amount==0:
            return 0
        tt = float('Inf')
        for i in range(len(self.coins)):
            if amount>=self.coins[i]:
                if self.amt[amount-self.coins[i]]==-1:
                    aa=1+self.coinC(amount-self.coins[i])
                else:
                    aa = 1 + self.amt[amount - self.coins[i]]
                tt = min(tt, aa)
        self.amt[amount]=tt
        return tt
    def coinChange(self, coins, amount):
        self.coins = coins
        # self.tt = float('Inf')
        self.amt = [-1 for i in range(amount+1)]
        ans = self.coinC(amount)
        if ans!=float('Inf'):
            print(ans)
        else:
            print(-1)

coins = [1, 2, 5]
amount = 11
s = Solution()
s.coinChange(coins, amount)

方法二:动态规划

思路:从前向后想,假设我有初始最优解,那么,我怎么求更大规模的最优解。就这一道题来说,当amount==0时,我最少需要找0个硬币,那更大规模的呢?怎么求解呢?如果是amount==1时,如果存在1元硬币,那么就返回1,否则,是无穷大,也就是没办法找;如果amount==2时,可以是因为amount>1,所以可以是1+f(2-1)=1+1=2,如果存在两元硬币的话,就是1+f(2-2)=1+0=1,将这两种方案比较,看哪个硬币个数少就要哪个,最后计算到amount==题目中所给的金额,即为所求。

dp[0]=0

dp[i]=1+min{dp[i-coins[j]]}(j=0, ..., len(coins)-1)

注意:这个也是只有i>=coins[j]时才更新

class Solution:
    def coinChange(self, coins, amount):
        dp=[float('Inf') for i in range(amount+1)]
        dp[0]=0
        for i in range(1, amount+1):
            tt = float('Inf')
            for j in range(len(coins)):
                if i>=coins[j]:
                    a = dp[i-coins[j]]
                    tt = min(tt, a)
            dp[i]=tt+1
        if dp[amount]==float('Inf'):
            return -1
        else:
            return dp[amount]

动态规划入门第一题,加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值