力扣:08.11. 硬币

127 阅读1分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

描述

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

解析

我们先遍历硬币,保证在考虑一枚硬币的情况时,没有较大的硬币影响,这样,我们最终每种组合情况,都是以硬币的面额大小非递减组合。保证了同样的情况,调换顺序后重复计算的情况。

当25的数量固定后,应该还有after25 = n - 25 * i的金钱来考虑三种硬币组合,为了方便,用t来表示吧 10的硬币可以有 t/10 张 采用0张时, 即i张25,0张10,方法有(t - 0 * 10) / 5 + 1种; 1张时, (t - 1 * 10) / 5 + 1; ...... t / 10 张时, (t - t / 10 * 10) / 5 + 1; (然后是等差数列求和,公差为2,注意带除的项不要轻易合并) 于是, i张25,剩下t = n - 25 * i余额时,三种金币组合方式有这么多种: t / 10 + 1 + (t / 5 + t / 5 - t / 10 - t / 10) * (t / 10 + 1) / 2

代码再简化一下,只剩一个for了 然后,res += 右边在计算时会可能大于INT_MAX, 所以t先用long接,之后再转回来。

class Solution {
    private static final int[] coins = {25, 10, 5, 1};
    private static final int mod = 1000000007;
    public int waysToChange(int n) {
        int[] temp = new int[n + 1];
        temp[0] = 1;
        for(int coin : coins) {
            for(int i = coin; i <= n; i++) {
                temp[i] = (temp[i] + temp[i - coin]) % mod;
            }
        }
        return temp[n];
    }
}
​

运行结果:

执行结果:通过

执行用时:25 ms, 在所有 Java 提交中击败了85.88%的用户

内存消耗:42.2 MB, 在所有 Java 提交中击败了61.69%的用户