目录
递归与分治
联系
递归三定律:
- 基本结束条件:解决最小规模问题;
- 缩小规模,向基本结束演进;
- 调用自身解决已缩小规模的相同问题:
即:
问题解决依赖于若干缩小规模的问题,这些问题结果汇总得到原问题的解
应用
排序、查找、遍历、求值
优化问题
最优解问题——兑换最少个数硬币问题
贪心策略
- 贪心策略
从最大面值的硬币开始,用尽可能多的数量
用最多数量的最大面值硬币来迅速减少找零面值
硬币的比值是由贪心策略制定的(Elbonia——杜撰国家中的21分硬币)
严格依赖于币值的体系
递归策略
- 递归策略
减小问题的规模——递归调用
def dpMakeChange(coinValueList,change,minCoins,coinsUsed):
for cents in range(change+1):
coinCount = cents
newCoin = 1 #最小规模,直接返回
for j in [c for c in coinValueList if c <= cents]:
if minCoins[cents-j] + 1 < coinCount:
coinCount = minCoins[cents-j]+1 # cent-j:减小规模(每次减去一种硬币面值)
newCoin = j
minCoins[cents] = coinCount
coinsUsed[cents] = newCoin
return minCoins[change]
def printCoins(coinsUsed,change):
coin = change
while coin > 0:
thisCoin = coinsUsed[coin]
print(thisCoin)
coin = coin - thisCoin
def main():
amnt = 63
clist = [1,5,10,21,25]
coinsUsed = [0]*(amnt+1)
coinCount = [0]*(amnt+1)
print("Making change for",amnt,"requires")
print(dpMakeChange(clist,amnt,coinCount,coinsUsed),"coins")
print("They are:")
printCoins(coinsUsed,amnt)
print("The used list is as follows:")
print(coinsUsed)
main()
但是,重复计算次数太多,因此递归算法改进的关键就是消除重复计算
将之前的最优解记录,在需要用的时候直接调用
动态规划解法
- 动态规划解法
之前中间结果记录称之为记忆化/函数值缓存(memorization)
从小往大,计算11=1+10(每次依靠之前已知的最优解)
能用动态规划解决问题的必要条件:问题的最优解包含了更小规模子问题的最优解
总结
- 递归式解决某些具有自相似性的复杂问题的有效技术;
- 递归算法“三定律“;
- 本质:不断减小问题的规模,调用自身,指导可以具备基本结束条件的解决为止;
- 递归通常能和问题的表达自然契合;
- 递归可能导致巨量的计算;
- 函数值缓存可以通过附加存储空间记录中间计算结果来有效减少重复计算;
- 如果一个问题最优解包括最小相同问题的最优解,则可以用动态规划解决(从小到大)
- 递归和动态规划二者之间可以相互转换