凑硬币

问题

现有面额为1元,3元,5元的硬币若干枚,如何用最少的硬币凑够11元?


拓展

保证各种面额的硬币数足够多,如何用最少的硬币凑够n元?


Java Code

//版本一:递归求解动态规划问题
public int minCoins(int n) {
    switch(n) {
        case 0: return 0;
        case 1: return 1;//面额依次为:1
        case 2: return 2;//面额依次为:1,1
        case 3: return 1;//面额依次为:3,
        case 4: return 2;//面额依次为:1,3
        case 5: return 1;//面额依次为:5
    }

    return Math.min(Math.min(minCoins(n-1), minCoins(n-3)), minCoins(n-5)) + 1;     
}

//版本二:递推求解动态规划问题
public int minCoins2(int n) {
    //数组minTable保存每一种总面额下需要的最少硬币数量
    int[] minTable = new int[n+1];
    minTable[0] = 0;
    minTable[1] = 1;
    minTable[2] = 2;
    minTable[3] = 1;
    minTable[4] = 2;
    minTable[5] = 1;

    for(int i=6; i < minTable.length; ++i)
        minTable[i] = Math.min(Math.min(minTable[i-1], minTable[i-3]), minTable[i-5]) + 1;

    return minTable[n]; 
}

说明

  • 解决动态规划问题的一般思路是通过分析寻找原问题的子问题,将原问题的求解转化为子问题的求解,原问题的子问题一般需要分情况讨论。我们可以总结规律得到状态转移方程即递推方程,一般情况下可能还需要总结所有可能的基本情况(比如本题中n=0,1,2,,,5这六种基本情况)。为了简化求解过程,通常需要将已经求解过的子问题结果保存起来(从基本情况开始迭代计算),以便下一次迭代时直接使用,这便是上述代码中的版本二递推解法,如果是从后往前逆推求解,由于当前情况的求解依赖于前一次求解的结果,所以需要用到递归,这便是上述代码中版本一的解法,这种解法的代码通常会显得更加简洁,但是效率不如递推法高。类似问题可以参考Leetcode - Nim Game

  • 本题的分析比较简单,n=0,1,2,,,5为基本情况,我们单独分析,从n=6开始,我们使用递推公式来求解最少的硬币数。由于硬币面额只有3种,所以当前总额n的最少硬币数等于n-1、n-3、n-5这三种情况下的最少硬币数的最小值再加1,这个加1就对应于当前次分别用面额等于1、3、5的一枚硬币来凑够n元。

  • 本题不能简单地认为把总额n中的n/5部分金额全部用面额为5的硬币凑,把剩下的的n%5部分金额用面额为1或3的硬币来凑,这种方案不一定就是最优解(本题给的三种面额用此方法正好就是最优解,所以本题可以给出更高效的解法)。举个简单的例子,如果所给的硬币面额为5,4,1三种,当n=8时,如果用本方案则需要的硬币面额分别为5、1、1、1,共需要4枚硬币,而实际上最优解只需要两枚4元硬币即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值