动脑子,兑换零钱了

287 阅读4分钟
1:题目


给定不同面额的硬币 coins ,每个值都代表一个面值的货币,每种面值都可以使用任意张,再给定一个总金额 amount,求换钱有多少种方法。


例如:

coins=[3, 5, 1], 总额amount = 11

组成的方法有5+5+1=11,3+3+5=11,3+3+1+1+1+1+1=11,3+3+3+1+1=11,

3+5+1+1+1=11,5+1+1+1+1+1+1=11,3+1+1+1+1+1+1+1+1=11,

1+1+1+1+1+1+1+1+1+1+1=11共8种。


2:要求

a:要求空间的复杂度为O(M*N),时间复杂度O(M*N)


3:解答

1:前几天我们通过动态规划解决了用最少的硬币兑换零钱的问题,那么这个题目是不是也可以和上次那个那样,通过动态规划来实现呢?


2:首先关于动态规划的定义,可以查看相关的文章。


3:我们来举一个例子,首先声明一个dp[amount+1][n]的数组


假如只有一枚3元硬币


组成0元金额的方法有一种,那就是所有的硬币都不用,所以返回1。


组成1元金额的方法没有,所以返回0种。


组成2元金额的方法没有,所以返回0种。


组成3元金额的方法有1种,所以返回1种。


组成4元,5元金额的方法没有,所以返回0种。


组成6元金额的方法有1种,所以返回1种


组成7元,8元金额的方法没有,所以返回0种。


组成9元金额的方法有1种,所以返回1种


组成10元,11元金额的方法没有,所以返回0种。


以次类推,我们可以得到如下的结果


金额 0 1 2 3 4 5 6 7 8 9 10 11

====================================

3元 1 0 0 1 0 0 1 0 0 1 0 0


那如果用2张硬币3元和5元会怎么样呢?


金额 0 1 2 3 4 5 6 7 8 9 10 11

====================================

3元 1 0 0 1 0 0 1 0 0 1 0 0

5元 1 0 0 1 0 1 1 0 1 1 1 0


为什么这么写?同理我们可以分析一下


组成0元金额的方法也只有一种,那就是所有的硬币都不用,所以返回1。


组成1元金额的方法同样没有,所以返回0种。


组成2元金额的方法同样没有,所以返回0种。


组成3元金额的方法有1种,那就是使用上面的3元硬币,所以返回1种。


组成4元金额的方法没有,所以返回0种。


组成5元金额的方法有1种,所以返回1种。


组成6元金额的方法有1种,那就是使用上面的3元硬币,所以返回1种。


组成7元金额的方法没有,所以返回0种。


组成8元金额的方法有1种,那就是一个3元硬币和一个5元硬币,所以返回1种。


组成9元金额的方法有1种,使用上面的3元硬币,所以返回1种


组成10元金额的方法有1种,所以返回1种


组成11元金额的方法没有,所以返回0种。


当用3种硬币的时候,我们再次分析一下。


金额 0 1 2 3 4 5 6 7 8 9 10 11

====================================

3元 1 0 0 1 0 0 1 0 0 1 0 0

5元 1 0 0 1 0 1 1 0 1 1 1 0

1元 1 1 1 2 3 4 5 5 6 7 8 8



为什么一下子多这么多种方式呢?


组成0元金额的方法也只有一种,那就是所有的硬币都不用,所以返回1。


组成1元金额的方法有一种,就是使用1元硬币,所以返回1种。


组成2元金额的方法有一种,所以返回1种。


组成3元金额的方法有2种,那就是使用上面的3元硬币或者是3个一元的硬币,所以返回2种。


以此类推,可以得到结果。


示例代码请参看这里

https://github.com/1260380285/suanfa/blob/yuanbing/src/com/Corns.java


4:代码



有些人可能对这一块有问题?

说明如下:

a)dp[i][j]=dp[i-1][j]是因为我们可以使用只有上面(i-1)硬币的情况

b)下面这个的意思是去掉当前的金额,剩余的金额还有几种组成方式


最后,如果好的话,记得留赞哦...

如果你觉得这篇文章有用,记得分享到朋友圈,关注下面的公众号,大家一起进步哦~




扫一扫 关注我的公众号

如果你想要跟大家分享你的文章或有问题,欢迎留言和投稿~

如果你喜欢,请留下你的赞哦