递归
1. 简介
递归核心思想是将问题不断分解成子问题,直到可以用普通方法解决;简单来说,在函数上通常表现为调用自己。递归算法必须满足以下三个原则:
① 存在基本情况;
② 不断迭代后,趋近基本情况;
③ 递归的调用自己。
例如:数列a1=1,a(n)=a(n-1)+n(n>1),a1=1是基本情况,a(n)=a(n-1)+n就不断的在趋近基本情况,计算a(n)需要先求出a(n-1),这就是不断的在递归调用自己,用代码表示如下:
def getSum(n): if n == 1: num_sum = 1 else: num_sum = getSum(n-1) + n #递归调用 return num_sum
2. 递归求解汉诺塔 问题
汉诺塔问题是非常经典的问题:有三根杆(A、B、C),在A杆自下而上、由大到小按顺序放置64个盘子,目标:把A杆上的盘子全部移到C杆上,并仍保持原有顺序叠好,且要求每次只能移动一个盘子,并在移动过程中三根杆上都始终保持大盘在下,小盘在上。如下图所示,三阶的汉诺塔问题演示如下。
简单推演可推导出5阶以内汉诺塔问题的移动步数,5阶之后就简单一步一步推演计算量可就很大了…,不过推导出前面几阶的步数之后,可以大致借助数列尝试进行找规律,当然汉诺塔问题移动步数规律早已知是:an=zn-1(n为盘子个数)
n阶汉诺塔问题 移动步数 1 1 2 3 3 7 4 15 5 31
递归思想
使用递归的思想来思考这个问题确实简单一些,先假设movetime(n)表示n个盘的移动次数,对于有n个盘子的汉诺塔,首先将n-1个看做一个整体,将n-1个盘子从A移动到B(移动次数:movetime(n-1)),再将n个盘子从A移向C(移动次数:1),再把B中的n-1个盘移向C(移动次数:movetime(n-1)),即完成移动过程,,总移动次数为movetime(n)=movetime(n-1)+1+movetime(n-1)=2*movetime(n-1)+1def movetime(n): if n==1: time = 1 else: time = 2*movetime(n-1)+1 return time
3. 递归求解斐波那契数列
斐波那契数列:
最先研究斐波那契数列的人是比萨的列奥那多,他在描述兔子生长数目用上了这数列:
第一个月初有一对刚诞生的兔子,第二个月之后(第三个月初)它们可以生育,每月每对可生育的兔子会诞生下一对新兔子,假设兔子永不死去,那么第n个月后会有多少对兔子?
解析:
当代兔子数量=上一代兔子数量+新出生的兔子数量。假设在n月有兔子总共an对,n+1月总共有an+1对(即出生an+1-an对新兔子),那么在n+2月出生的兔子就有an+1-(an+1-an)=an
对,则第n+2月兔子总数就为an+2=an+an+1def fib(n): if n == 0: num = 0 elif n == 1: num = 1 else: num = fib(n-1) + fib(n-2) return num