数据结构26:找零兑换问题的递归解法

57 篇文章 12 订阅
47 篇文章 12 订阅

目录

一、找零兑换问题:递归解法

二、找零兑换问题:递归解法代码

三、递归解法分析

四、递归解法改进代码


一、找零兑换问题:递归解法

 

我们来找一种肯定能找到最优解的方法

首先确定基本结束条件,兑换硬币这个问题最简单最直接的情况就是,需要兑换的找零,其面值正好等于某种硬币。

其次是减小问题规模,我们要对每种硬币尝试一次,例如美元硬币体系:

  • 找零减去1分后,求兑换硬币最少数量(调用自身);
  • 找零减去5分后,求兑换硬币最少数量;
  • 找零减去10分后,求兑换硬币最少数量;
  • 找零减去25分后,求兑换硬币最少数量;

上述4项中,选择最小的一个。

 

二、找零兑换问题:递归解法代码

def recMac(coinValueList, change):
    minCoins = change
    if change in coinValueList:
        return 1
    else:
        for i in [c for c in coinValueList if c<= change]:
            numCoins = 1 + recMac(coinValueList, change - i)
            if numCoins < minCoins:
                minCoins = numCoins
    return minCoins

三、递归解法分析

递归解法虽然能解决问题,但是其最大的问题是:极其低效

以63分的兑换硬币为例,需要进行67716925词递归调用,在笔记本上需要话费40s时间得到解。

以26分硬币兑换为例,看看递归调用的过程(377词递归的一小部分)

对这个递归解法进行改进的关键就是消除重复计算,我们可以用一个表将计算过的中间结果保存起来,在计算之前查表看看是否已经计算过。

这个算法的中间结果就是部分找零的最优解,在递归调用中已经得到的最优解被记录下来。这样的话,在递归调用之前,先查找表中是否已有部分找零的最优解,如果有,直接返回最优解而不进行递归调用,如果没有才进行递归调用。

四、递归解法改进代码

def recMac(coinValueList, change, knowResults):
    minCoins = change    # 当前的钱数
    if change in coinValueList:   # 递归基本结束条件
        knowResults[change] = 1   # 记录最优解
        return 1
    elif knowResults[change] > 0:
        return knowResults[change]    # 查表成功,直接用最优解
    else:
        for i in [c for c in coinValueList if c <= change]:
            numCoins = 1 + recMac(coinValueList, change - i, knowResults)

            if numCoins < minCoins:
                minCoins = numCoins
                # 找到最优解,记录到表中
                knowResults[change] = minCoins
    return minCoins

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值