面试题 08.11. 硬币
硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007)
示例1:
输入: n = 5
输出:2
解释: 有两种方式可以凑成总金额:
5=5
5=1+1+1+1+1
示例2:
输入: n = 10
输出:4
解释: 有四种方式可以凑成总金额:
10=10
10=5+5
10=5+1+1+1+1+1
10=1+1+1+1+1+1+1+1+1+1
说明:
注意:
你可以假设:
- 0 <= n (总金额) <= 1000000
解法
这个和官方题解里面的方法一类似,但是有一点差别。
官方题解里面,最后得到的是:
举例来说,如果我想要用4种硬币(分别是1、5、10、25)来凑成100分,那我可以先算出来用3种硬币(1、5、10)凑成100分的方法,再算出来用4种硬币(1、5、10、25)凑成75分的方法数,把他们加起来。
这样的好处是,我们可以只用前面的数据算出来的数据,就不用存所有行了。
我这里的解法稍微差一些,是记录了四个数组,分别表示:最大用了1分、最大用了5分、最大用了10分、最大用了25分的前提下的种类数。
如果我想要用4种硬币(分别是1、5、10、25)来凑成100分,那我可以先算出来:
- 用最大为25的硬币(也就是说,用了4种硬币(1、5、10、25)并且必须有25)凑成75分的方法;
- 用最大为10的硬币(也就是说,用了3种硬币(1、5、10)并且必须有10)凑成75分的方法;
- 用最大为5的硬币(也就是说,用了2种硬币(1、5)并且必须有5)凑成75分的方法;
- 用最大为1的硬币(也就是说,用了1种硬币(1)并且必须有1)凑成75分的方法。
最后加起来就是总的方法数。
不如csx大佬的官方题解,但是也是正确的做法。
class Solution {
public:
int waysToChange(int n) {
if (n == 0) {
return 1;
}
vector<int> dp_max_1(n + 1, 1);
vector<int> dp_max_5(n + 1, 0); // 必须有至少一个5
vector<int> dp_max_10(n + 1, 0);
vector<int> dp_max_25(n + 1, 0);
for (int i = 5; i <= n; i++) {
dp_max_5[i] = (dp_max_1[i - 5] + dp_max_5[i - 5]) % 1000000007; // use one 5, will get dp_max_1[i - 5]; use two 5s, dp_max_5[i - 5]
}
for (int i = 10; i <= n; i++) {
dp_max_10[i] = (dp_max_1[i - 10] + dp_max_5[i - 10] + dp_max_10[i - 10]) % 1000000007;
}
for (int i = 25; i <= n; i++) {
dp_max_25[i] = (dp_max_1[i - 25] + dp_max_5[i - 25] + dp_max_10[i - 25] + dp_max_25[i - 25]) % 1000000007;
}
return (dp_max_1[n] + dp_max_5[n] + dp_max_10[n] + dp_max_25[n]) % 1000000007;
}
};
网友评论