数据结构-动态规划之找零钱

美元的硬币面值为1美分、5美分、10美分和25美分。找零钱数为63美分,最少的方案时2个25,1个10,3个1一用6枚硬币。

可以使用贪婪法来找硬币,但是事实并非总是如此。

例如,如果硬币面值多了一个21的,很明显最少的方案是3个21美分的,而不是6个硬币,但,贪婪法无法解决此类问题。即贪婪法只能保证局部最优,不能保证全局最优。

考虑第一种方法,使用递归,计算所有可能组合的最小数目。

首先,最大的方案就是1来填补,但是这里利用的是将63划分为不同的两份,从(1,62)、(2,61)......(31,32),然后以此递归每个分量。这样的计算量堪比fib数列,效率是非常低的。

public static int getMinMoneyR(int[] cons,int money){
    int minCoin = money;
    for(int i=0;i<cons.length;i++){
        if(cons[i]==money)
            return 1;
    }
    for(int i=1;i<=money/2;i++){
        int thiscoin=getMinMoneyR(cons,i)+getMinMoneyR(cons,money-i);
        if(thiscoin<minCoin)minCoin=thiscoin;
    }
    return minCoin;
}

考虑第二种方法,使用动态规划。动态规划的实质是将结果进行保存,每次计算的时候查表,降低计算的复杂度。

public static int getMinMoney(int[] cons,int money){
    int mincoin=0;
    int[] consused = new int[money+1];
    //建表查表的过程,针对从1money的所有可能的最小方案
    for(int i=1;i<=money;i++){
        mincoin=i;//设置成最大,假设全是1
        for(int j=0;j<cons.length;j++){
            if(cons[j]<=i){//当硬币面值小于等于i的时候,计算最小硬币数量
                //举例子,consused[0]=0,consused[1]=min{1,0+1}=1,consused[2]=min{min{2,1+1},0+1}=1
                mincoin=Math.min(mincoin,consused[i-cons[j]]+1);
            }
        }
        consused[i]=mincoin;
    }
    return consused[money];
}
时间复杂度是O(kn),其中k是硬币的个数,n是要找的零钱数。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值