目录
一、找零兑换问题:递归解法
我们来找一种肯定能找到最优解的方法
首先确定基本结束条件,兑换硬币这个问题最简单最直接的情况就是,需要兑换的找零,其面值正好等于某种硬币。
其次是减小问题规模,我们要对每种硬币尝试一次,例如美元硬币体系:
- 找零减去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