[路飞]_518. 零钱兑换 II

33 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

今天我们来做一下leetcode上面的一道比较经典的题目518. 零钱兑换 II,它也是 322. 零钱兑换的一个延申

题意

image.png

与322题意类似,同样给了我们若干个面额不同的硬币无限个,和一个总金额,只不过这一次让我们求组成的总金额的不同组合方式的个数。

思路

既然求组合数,也就是区分于排列数而讲的,这意味这如果两个凑成金额的方式如果只有硬币的顺序不同,那么他们算一种组合,具体的,如果使用1、2、5组成金额5,那么 1 2 2和2 2 1是相同,也就是先拿1硬币和后拿1硬币 是一样的方法。

既然忽略顺序,那么我们在拿硬币的时候只要按照顺序拿就可以了,也就是我们从面额小的到面额大的拿。

具体的,比如示例1 amount=5 coins=[1,2,5] 定义dp[i]为凑成金额i的组合数,所以dp[0]=1,也就是什么硬币都不拿,也是一种方法

  • 拿硬币1,凑成金额1 2 3 4 5的组合都只有一种,即dp[1]=dp[2]=dp[3]=dp[4]=dp[5]=1
  • 拿硬币2,
    • 凑成金额2的组合数 = 等于当前选择2的组合数(当前选择2,剩余金额0,也就是求金额0的组合数) + 前面计算出的dp[2]的值,即dp[2] += dp[2-2],dp[2] = 1 + 1 = 2
    • 凑成3的组合有2种,所以到现在为止 dp[3] += dp[3-2] dp[3] = 1 + 1 = 2
    • 凑成4的组合有2种,所以到现在为止 dp[4] += dp[4-2] dp[4] = 1 + 2 = 3
    • 凑成5的组合有3种,所以到现在为止 dp[5] += dp[5-2] dp[5] = 1 + 2 = 3
  • 拿硬币5
    • 凑成金额5的组合数有1种,所以到现在为止 dp[5] += dp[5-5] dp[5] = 3 + 1 = 4

这样一来,我们按照硬币的顺序,分别累加求出各个金额的组合数之后, 也就是得到了最终凑成金额amount的组合数了。

代码实现

image.png

结束语

如果有更好的分析思路,欢迎大家在评论区发表看法!⛄