322. 零钱兑换
问题描述:
给定不同面额的硬币coins
和一个总金额amount
。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1
。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
- 你可以认为每种硬币的数量是无限的。
问题分析:
动规题目,仔细看看,这个有点类似于上台阶问题了,意思就是最后到达总金额amount
,有几个路径?废话不多说了,直接分析:
(1)可以这样思考,最后到达总金额amount
,有几中可能?很显然有几种硬币就有几种可能。这就形成了从前一个状态到后一个状态的转变。可以得出动规方程式:
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
解释:
dp[i]
表示金额为 i 时的,最少硬币数,那么这个值怎么求?就是,把i - coins[j]
此时的最少硬币数加一
,就是当前的值,很显然有很多硬币,所以要选择出一个最小的值。
Python3实现:
# @Time :2019/01/17
# @Author :LiuYinxing
# 动态规划
class Solution:
def coinChange(self, coins, amount):
""" :type coins: List[int] :type amount: int :rtype: int """
dp = [0] + [amount+1] * amount # 初始化dp
for i in range(1, amount+1):
for coin in coins:
if i >= coin: # 循环所有硬币,找到一个最少的一个
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[-1] if dp[-1] != amount+1 else -1
if __name__ == '__main__':
solu = Solution()
coins, amount = [1, 2, 5], 11
print(solu.coinChange(coins, amount))
声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。