在程序中,递归与递推的关系一目了然。递归即函数调用自身,而递推是一种迭代。然而,在数学定义上,我们往往认为递归是递推的一种特殊形式,仅仅表现在其公式仅由前几项式表示。因此,此处为了部分统一程序与数学中概念,姑且认为递归与递推是等价的,仅是二者表现形式不同。
首先,我将站在程序的角度上对递归与递推进行说明。递归通常和递推完成的是相同的操作,然而,递归却总是慢于递推。这是什么原因造成的呢?我们可以从形式上去分析。
先从递推说起。一个数列的递推仅仅由一个数组和循环构成,在空间上,存储了一个数组,在时间上,计算机十分擅长迭代。我们再来看递归。递归往往是以一个函数的形式存在,并且在函数体的内部还调用了自身,执行完毕后再回到当前调用的函数。我们不难想到,在这期间,之前的函数信息一定被保存了下来。事实果真如此。这样的递归函数通常是由调用栈负责。由此可见,在空间上,没什么问题,但在时间上,程序执行跨度很大导致相对缓慢,因此我们得出了一个结论,递推总比递归好。好吧,其实不能完全这么说,毕竟递归能完成许多递推不能完成的事,比如图上DP等。总之,写程序能用递推尽量用递推(其实我觉得许多时候都没有必要递归转递推,递归稍慢,但好写啊)。
以下是斐波那契数列的递归与递推写法:
递归:
int fib(int x){
return x>2?fib(x-1)+fib(x-2):1;
}
递推:
int f[1000]={
0,1,1};
int fib(int x){
for(register int i=3;i<=x;++i)f[i]=f[i-1]+f[i-2];
return f[x];
}
由此不难看出他们之间的特点。
接下来,我将谈谈数学中的这些方面。不管是递归还是递推,在这里都同等看待——一行能从已知得到未知的式子。注意,这是一个过程,并不是一个由起点直接到终点方式。但是,我们总能感受到,若是有一个能直接求出第 n 项的公式,运算速度不知道要快多少。因此,我们就不得不涉及通项公式。
首先拿一个经典的例子举例:
平面上的直线问题
平面上n条直线所界定的区域的最大个数Ln是多少?
刚拿到这个问题,可能的确感到棘手。我们首先会去枚举,
我们考虑第 n 条直线与之前的