一、递归算法
递归出口:递归终止条件
递归体:分而治之,将大问题转换成小问题,逐步求解
二、递归实例
实例一:
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第3个月又生一对兔子,假如兔子都不死, 从控制台输入第N个月,显示此时兔子总数(对)。
月份 | 兔子数(对) | 递归算法 |
1 | 1 | 1 |
2 | 1 | 1 |
3 | 2 | 1+1 |
4 | 3 | 2+1 |
5 | 5 | 3+2 |
6 | 8 | 5+3 |
7 | 13 | 8+5 |
8 | 21 | 13+8 |
9 | 34 | 21+13 |
10 | 55 | 24+21 |
根据表格的规律可知,当月的兔子总数=上个月兔子总数+上上个月的兔子总数,第1、第2个月的兔子数为1对
递归出口:第1个月、第2个月的兔子总数是1对
递归体:当月的兔子总数=上个月兔子总数+上上个月的兔子总数
代码实现:
def rabbit(month):
if month <=2:
return 1
else:
return rabbit(month-1)+rabbit(month-2)
测试用例:
for i in range(1,11):
print(rabbit(i),end = " ")
# 测试结果
# 1 1 2 3 5 8 13 21 34 55
实例二:
list = [1, 2, 3, [4, 5, 6, [7, 8, 9]], 10, [11, [12, [13, 14]], 15], 16]
将list转换成[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
分析:将多维列表转换成一维列表
递归出口:当列表中的元素类型不是list类型,则输出到一维列表中
递归体:高维列表转换为低维列表
代码实现:
def func(list_target):
result = []
for item in list_target:
if type(item) == type(list):
for i in func(item):
result.append(i)
else:
result.append(item)
return result
测试用例:
list = [1,2,3,[4,5,6,[7,8,9]],10,[11,[12,[13,14]],15],16]
print(func(list))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
实例三:
猴子吃桃子问题,每天吃一半多吃一个,请问10天前共有多少个桃子?
分析:
最后1天,有1个桃子
假设倒数第2天有x个桃子,根据吃桃子的规则可以用表达式,
计算出最后一天的桃子数:(x/2)-1=1
倒推求得倒数第2天的桃子数x = (1+1)*2=4
同理,推导出倒数第3天桃子数为:(4+1)*2=10
同理,推导出倒数第4天桃子数为:(10+1)*2=22
同理,推导出倒数第5天桃子数为:(22+1)*2=46
。。。。。。
逆向推导 | 正向推导 |
最后1天:1个 | (4/2)-1=1 |
倒数第2天:(1+1)*2=4 | (10/2)-1=4 |
倒数第3天:(4+1)*2=10 | (22/2)-1=10 |
倒数第4天:(10+1)*2=22 | (46/2)-1=22 |
倒数第5天:(22+1)*2=46 | (94/2)-1=46 |
倒数第6天:(46+1)*2=94 | (190/2)-1=94 |
...... | ...... |
天数 | 桃子个数 |
1 | 1 |
2 | 4 |
3 | 10 |
4 | 22 |
5 | 46 |
6 | 94 |
7 | 190 |
8 | 382 |
9 | 766 |
10 | 1534 |
递归出口:最后1天,有一个桃子,天数n==1时,桃子数count = 1
递归体:每天吃一半多吃一个,count/2-1
代码实现:
def foo(n,count):
if n == 1:
return count
else:
count = (count+1)*2
return foo(n-1,count)
测试用例:
if __name__ == '__main__':
print(foo(10,1))
三、最后总结
1、对于复杂的递归问题,先从简单的子问题入手,找到其中的规律,可以用笔演算
2、确定递归出口
3、分析大问题与小问题之间的关系与联系,用递归的思想设计递归体
4、测试用例测试递归是否正确