题目描述:
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例2:
输入:coins = [2], amount = 3
输出:-1
示例3:
输入:coins = [1], amount = 0
输出:0
思路1:
深搜,找到所有可能的方案,再取最小的,这里可以适当的剪枝,如从cions[i]最大的开始搜。 时间复杂度O(2^n)。
思路2:
动态规划——dp[i]拼到最少需要的数量
这道题类似与上台阶问题的思路,状态转移方程:
dp[i] = max{ dp[i-cions[j]] } +1, j : 是coins中所有值
即问题相当于倒数,比如示例1中可以是dp[6] + 1(再来一张5元), dp[9] + 1(再来一张2元), dp[10]+1(再来一张1元).
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
# 状态dp是凑成i需要的硬币数量
# 本题的状态定义和状态转移和爬楼梯问题很类似
dp = [amount+1 for i in range(amount+1)]
# 初始值的设置!!!
dp[0] = 0
for m in range(1, amount+1):
for j in range(len(coins)):
if m-coins[j] >= 0:
dp[m] = min(dp[m-coins[j]], dp[m])
dp[m] += 1
if dp[amount] <= amount:
return dp[amount]
else: #拼不出来!!!
return -1
这里需要注意初始值的设置来保证最后返回的结果是正确的,因为有拼不出来的情况。