递归应用——贪心策略解决找零问题的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
测试结果:

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

你可能感兴趣的:(数据结构与算法-python版,python,数据结构,贪心算法)