程序员面试金典08.11-硬币

原题(来源Leetcode)

硬币。给定数量不限的硬币,币值为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

解法

思想

动态规划,不过需要注意排列组合去重

代码

常见错误是:

class Solution {
    public int waysToChange(int n) {

        int[] dp = new int[n + 1];

        int[] coins = new int[]{1,5,10,25};

        for(int i = 1; i <= n; i++) {
            for(int coin: coins) {
                if(i - coin < 0) break;
                dp[i] = (dp[i] + dp[i - coin]) % 1000000007;
            }
        }

        return dp[n];
    }
}

然而却忽略了重复的情况,例如6可以由1+5组合来,也可以由5+1组合来。

正确的答案其实只是将内外循环换了个顺序,保证这些数字是按递增的方式组合的,就能做到去重。:

class Solution {
    public int waysToChange(int n) {

        int[] dp = new int[n + 1];

        int[] coins = new int[]{1,5,10,25};

        for(int coin : coins) {
            for(int i = coin; i <= n; i++) {
                dp[i] = (dp[i] + dp[i - coin]) % 1000000007;
            }
        }

        return dp[n];
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e7%a8%8b%e5%ba%8f%e5%91%98%e9%9d%a2%e8%af%95%e9%87%91%e5%85%b808-11-%e7%a1%ac%e5%b8%81/