递归应用——贪心策略解决找零问题的python实现

引言

找零问题:兑换最少个数的硬币
贪心策略:每次以最多数量的最大面值的硬币来迅速减少找零面值,若有余额,再到下一个最大面值的硬币,还用尽量多的数量,逐面值查找,直接面值为1结束。

递归条件

基本结束条件:需要兑换的找零,其面值正好等于某种硬币的数倍,没有余额。
减小问题的规模:对每种硬币尝试一次,分别将找零减去1、5、10、25后,求兑换硬币的最少数量(递归调用自身)。

代码实现一:

def recMC(coinvaluelist,change):
    mincoins=change
    if change in coinvaluelist:
        return 1
    else:
        for i in [c for c in coinvaluelist if c<=change]:
            numcoins=1+recMC(coinvaluelist,change-i)
            if numcoins<mincoins:
                mincoins=numcoins
        return mincoins

print (recMC([1,5,10,25],63))
##记录运行时间:
import time
print(time.clock())
print (recMC([1,5,10,25],63))
print(time.clock())
#测试结果
3e-07
6
82.5235314

该算法缺陷:效率低下,因为重复计算太多

递归解法改进版:

解决重复计算的方法:用一个表将计算过的中间结果保存起来,下次计算前查表看是否计算过。
这个算法的中间结果就是部分找零的最优解,在递归调用过程中已经得到的最优解被记录下来。在递归调用之前,先查表看是否已有部分找零的最优解,若有,则直接返回最优解而不递归调用;若没有,才进行递归调用,直至结束。
改进python代码:

def recDC(coinvaluelist,change,knownresults):
    mincoins=change
    if change in coinvaluelist:  #递归基本结束条件
        knownresults[change]=1   #记录最优解
        return 1
    elif knownresults[change]>0:
        return knownresults[change]  #查表成功,直接用最优解
    else:
        for i in [c for c in coinvaluelist if c<=change]:
            numcoins=1+recDC(coinvaluelist,change-i,knownresults)
            if numcoins<mincoins:
                mincoins=numcoins   
                knownresults[change]=mincoins   #找到最优解,记录到表中
        return mincoins
import time
print(time.clock())
print (recDC([1,5,10,25],63,[0]*64))
print(time.clock())
3e-07
6
0.0009077
测试结果:

计算时间大幅度缩短,结果秒回!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笨猪起飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值