看了一些教递归的博客,感觉就是两个字——不对
总是感觉他们的理解非常的主观抽象,不太科学,而且概念很突兀。因此,我尝试用高中的数学知识来解释递归,并且尝试去设计一个递归,用python来实现。
首先,打开你们高中的记忆区,我们大部分程序员都是从高中上来的人,这种函数大家肯定都解过:
x=80,求f(x)的值
我相信你们一看就看出来了。先找到定义域,然后带入求值。
特别的是我们作为程序员是可以把这个公式代码化的,然后不去手算,用电脑去算,你要有这个概念。
然后,这个函数你们也肯定有印象,而且做过:
x=4,求f(x)的值
当初我们高中的时候是怎么算的?找定义域,代数进去,算,找定义域,代数进去算。我现在回过头来看,这个就是递归嘛,再仔细看看,这不是我们搞编程的学递归的第一个编程题,斐波那契数列嘛。
f(n) = 1、1、2、3、5、8、13、21、34……
那我们看着上面的数学公式,再去写出这个所谓的递归算法,试试
def fun1(x):
# 这里是一部分的定义域
if x == 1 or x == 2:
return 1
# 这里是另一部分的定义域
return fun1(x - 1) + fun1(x - 2)
if __name__ == '__main__':
i = 5
print(f'第{i}位的值是:{fun1(i)}')
水到渠成,非常的简单,直接就写出来了。你写的时候就把定义域的部分往if条件里塞,函数部分就往if的代码块,或是else里塞。
按照这个来看,我们大部分人都能通透的理解这个例子了,但是这个不是通解,我们需要一套严密而标准的流程方法来解决递归问题。而这个流程方法,就在例子中,需要你敏感的提取出来。我来告诉你我的思考。
回溯一下,我们是不是先有公式,然后用高中知识求解公式玩玩,发现公式正确,最后用大学知识编码知识实现公式的?没错,这整个环节和递归有关的是那个公式的设计,所以我们应该先思考公式,再去思考代码方面的东西。
思路:公式→代数测试→代码实现公式
在面对大的递归问题时,这里的每一步,都是有难度的,但是一定是按这个顺序的,否则你会很混乱。
那我们怎么去设计这个公式呢?我们从数学的方面看这个公式,最重要的东西就是高中老师长谈的"定义域",这个东西帮我们划分好了,输入值应该归哪个函数管理。
所以我们遇到递归问题,应该先优先按题目要求,力所能及的取划分定义域,再确定该定义域下的函数主体。然后用数学函数的方式,把每一块表达出来,这样算法就能实现。
这种方法是我参考了我在程序设计的时候画完uml再写代码,这样我的工程化设计会井井有条,而在算法这边我发现没有人认真的讲过可以用这种数学工具来辅助算法设计的,也算是我的一点理解。