HOT100-21-零钱兑换
题目描述
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
示例 1:
plaintext
1 | 输入:coins = [1, 2, 5], amount = 11 |
具体见题目详解。
算法思路
对于这种问题,我最开始想的是贪心,因为你想让金币数量尽可能的少,还需要凑齐数额,就需要用尽可能大的金币面值。但这很显然进入了一个误区:全局最优并不代表局部最优。举个例子,对于 amount = 19, coins = [1, 6, 7]
,如果从最大的硬币开始数,那么就是2个coin-7,5个coin-1,总共需要7个硬币;但是很显然,如果选取coin-6和coin-1,那么只需要4个就行了,最后这个想法肯定是没通过的,这里就不展示代码了。
后来我看了一下这个题目的标签,提示是动态规划,这样就很同意想清楚了,你要凑齐j元硬币,那么至少在[1~j]
之间的某个数额(后面会讲具体的)你肯定能凑出来,否则这个j肯定是凑不出来的。
具体来说,我们记dp[i]
为凑齐 i
所需要的最小的金币数量,那么对于之前已经凑出来的i-coins[k], k= 0,1, ...n
,我们只需要找到最小的dp[i - coins[k]]
,在此基础上加1(加上coins[k])就能得到数额i。
因此,我写的代码如下:
cpp
1 | class Solution { |
总体思路是这样的,但是有点丑长了,效率也不咋地,但是和我同样的官方思路效率就非常快,可以看看他的代码:
cpp
1 | class Solution { |
还有一种思路是广搜,也就是我们常说的暴力,纯暴力是百分百过不了的,需要加上记忆搜索,我这里就不写了,对这种解法不是很感兴趣,想看的点击此处自行查看。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.