问题
给你 k 种面值的硬币,面值分别为 c1, c2 ... ck ,
每种硬币的数量无限,再给一个总金额 amount ,
问你最少需要几枚硬币凑出这个 金额,如果不可能凑出,算法返回 -1
思路
要凑出金额 11,至少要 dp(coins,11) 个硬币;
假如第一次凑1块,那么还有11-1块需要凑,要凑出金额 11-1,至少要 dp(coins,11-1) 个硬币;
假如第二次还是凑1块,那么还有10-1块需要凑,要凑出金额 10-1,至少要 dp(coins,10-1) 个硬币;
……
……
直到amount==0,刚好凑齐,否则无效
代码实现
package main
import (
"fmt"
"math"
)
func main() {
var coins = []int{1, 2, 5}
num := coinChange(coins, 11)
fmt.Println(num)
}
// 凑零钱问题
func coinChange(coins []int, amount int) int {
if amount == 0 {
return 0
}
return helper(coins, amount)
}
func helper(coins []int, amount int) int {
if amount == 0 {
return 0
}
if amount < 0 {
return -1
}
res := math.MaxInt32
for _, coin := range coins {
tmp := helper(coins, amount-coin)
if tmp == -1 {
continue
}
res = min(res, tmp+1)
}
if res == math.MaxInt32 {
return -1
}
return res
}
func min(a, b int) int {
if a <= b {
return a
}
return b
}
- 当然,其中还存在可以继续优化的地方,我们可以利用备忘录map记录已经计算过的,再次需要计算,直接从map中获取即可