面试题 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
解答:
一两周没怎么刷题,中等题都要看题解了。。原来是一个完全背包问题,妈蛋看过阿,怎么没联想出来呢?
二维dp:
class Solution { public: int waysToChange(int n) { vector<vector<int> >dp(4,vector<int>(n+1,0)); vector<int> value={1,5,10,25}; dp[0][0]=1; dp[1][0]=1; dp[2][0]=1; dp[3][0]=1; for(int i=0;i<4;++i){ //dp[i][j]:只用前i种硬币,达到j币值的方法数 for(int j=1;j<=n;++j){ if(i>0){ dp[i][j]+=dp[i-1][j]; } if(j-value[i]>=0){ dp[i][j]+=dp[i][j-value[i]]; } dp[i][j]%=1000000007; } } return dp[3][n]; } };

由于dp递推关系中dp[i][j]只需要用到dp[i-1][j]和dp[i][j-coins[i]],也就是只用到了上一行、当前列之前的结果。
那么可以优化dp数组到一维:
class Solution { public: int waysToChange(int n) { vector<int>dp(n+1,0); vector<int> value={1,5,10,25}; dp[0]=1; for(int i=0;i<4;++i){ for(int j=value[i];j<=n;++j){ dp[j]=(dp[j]+dp[j-value[i]])%1000000007; } } return dp[n]; } };

进击的小🐴农

浙公网安备 33010602011771号