前言
如果一谈到“递归”你的脑海就浮现出“自己调用自己”,我想说:“你可能并不懂递归”。当然了,这仅仅是个人鄙见。许多时候,递归确实在“自己调用自己”。我们知道这个道理吧,想用递归解决实际问题却又犯难了——怎么就写不出代码来了呢?
我想异于网上千篇一律文章的讲法,小小的别开生面一回,用自己认为容易理解的方式来阐述递归思想。当然啦,如同标题所说,只能浅谈而已。因为,我并不认为自己已经很懂。
递归的形态
如前言所说,大多数时候递归是自己调用自己。其形式应该如下:
# 示例一
def print_alpha():
print("z")
print_alpha() # 在自己的内部调用自己
if __name__ == "__main__":
print_alpha()
然而这样的递归并不可取。尽管上边代码的效果与一个死循环一样:
# 示例二
def print_alpha():
while True:
print("z")
if __name__ == "__main__":
print_alpha()
但因为递归过程中会保留过程中产生的各种数据,十分耗费系统资源,所以一般编程语言会限制递归的深度。拿Python为例,运行示例一的代码能看到解释器抛异常如下:
RecursionError: maximum recursion depth exceeded while calling a Python object
所以递归的另一个重点在于:需要一个出口,一个可以退出递归的出口。
就好像这样:
def print_alpha(num):
# 递归出口
if num <= 0:
return
print("z")
print_alpha(num-1)
if __name__ == "__main__":
# num 为打印字母的次数
print_alpha(num=10)
归纳法
现在,我想说说高中数学涉及到的归纳法。
高中学习数列的时候老师应该会先讲一个名为归纳法的东西引我们入门,不知各位还记不记得。我是印象深刻的,因为这玩意儿简单好用实在(刚学数列的时候不存在特别难题),但问题是:考试不让用。老师说归纳法只能用来分析题,要证明啊计算啊什么的都得用公式。就不管你是等差求和还是等比求和了。
好,有请著名的斐波拉契数列登场:
1 , 1 , 2 , 3 , 5 , 8 , 13 , . . . 1, 1, 2, 3, 5, 8, 13, ... 1,1,2,3,5,8,13,...
进入提问环节:第8个数应该是多少?
题不存在难度,相信大家很快得出答案为21。为什么呢?因为通过观察发现,从第三个数开始,它的值永远等于前面两个数的和。所以第8个数就应该是: 8 + 13 = 21 8 + 13 = 21 8+13=21。这样一个我们思考的过程就是归纳法。
递归的思想
编程中的递归就是数学中的归纳法演变过来的。我们通过发现的规律,将场景演化成代码。
这里还是说斐波拉契数吧。如何用代码计算斐波拉契数列中的第n个数的值呢?回忆一下归纳法中斐波拉契数的规律:a. 第一、二个数总为1;b. 从第三个数开始,它的值