题目
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例
输入:coins = [1, 2, 5], amount = 11 输出:3 解释:11 = 5 + 5 + 1
解析
这道题和之前的零钱兑换区别是,之前是问有多少种兑换方法,本题是问最少硬币个数,先用动规五部曲分析一波: 1.确定dp数组以及下标的含义 dp[j]:凑足总额为j所需钱币的最少个数为dp[j] 2.递推公式 凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i],注意,这里是加一个硬币,数量是1 就可以了,即dp[j - coins[i]] + 1就是dp[j](考虑coins[i]) dp[j] = min(dp[j - coins[i]] + 1, dp[j]); 3.初始化 凑成总金额为0需要的最小硬币数量一定是0,所以dp[0] = 0 除此之外,因为要求最小值,那么比较的时候,要先把整个数组初始化为最大值才行 4.遍历顺序
func coinChange(coins []int, amount int) int {
dp := make([]int, amount+1)
dp[0] = 0
for i := 1; i < amount+1; i++ {
dp[i] = math.MaxInt32
}
for i := 1; i <= amount; i++ {
for j := 0; j < len(coins); j++ {
if i - coins[j] >= 0 {
dp[i] = min(dp[i], dp[i-coins[j]]+1)
}
}
}
if dp[amount] == math.MaxInt32 {
return -1
}
return dp[amount]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
|