去的过程叫递, 回的过程叫归。
递归的两个特点:
调用自身;
结束条件;
1. 斐波那契数列
1 1 2 3 5 8 ...
终止条件
f(0) = 1
f(1) = 2
递推公式
f(n) = f(n-1) + f(n-2)
方式1:
def fibnacci(n): # O(2^n)
if n == 0 or n == 1:
return 1
else:
return fibnacci(n-1) + fibnacci(n-2)
方式2:
def fib2(n):
li = [1,1]
for i in range(2, n+1):
li.append(li[-1]+li[-2])
return li[n]
时间复杂度和空间复杂度都是O(n)。
方式3:通过移位的方式进行替换,更节省时间和空间。时间复杂度O(n),空间复杂度O(1)
def fib3(n):
a = 1
b = 1
c = 0
for i in range(2, n+1):
c = a + b
a = b
b = c
练习题
一段有n个台阶组成的楼梯,小明从楼梯的最底层向最高处前进,它可以选择一次迈一级台阶或者一次迈两级台阶。问:他有多少种不同的走法?
先看看1,2,3,4,5个台阶时,分别有几种结果,发现规律:只要在最前面加上1,就是斐波那契。
递归问题的分析思路是把一个拆开,剩下的看成整体。
2、汉诺塔问题
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。 在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 64根柱子移动完毕之日,就是世界毁灭之时。
image
n=2时:
1.把小圆盘从A移动到B
2.把大圆盘从A移动到C
3.把小圆盘从B移动到C
n个盘子时:
1.把n-1个圆盘从A经过C移动到B
2.把第n个圆盘从A移动到C
3.把n-1个小圆盘从B经过A移动到C
把这个问题看成第n-1个和第n个的问题,把第n-1个当做整体。
def hanoi(n, A, B, C):
if n > 0:
hanoi(n-1, A, C, B)
print('%s->%s' % (A, C))
hanoi(n-1, B, A, C)
# h(n) = 2h(n-1)+1
hanoi(64, 'A', 'B', 'C')
汉诺塔移动次数的递推式:这是一个指数级增长的问题
h(n)=2h(n-1)+1
h(64)=18446744073709551615 假设婆罗门每秒钟搬一个盘子,则总共需要5800亿年!