昨天简单看了一下递归是怎样实现的。简单的说就是把要处理的元素入栈,每次处理先处理栈顶的元素,如果遇到子函数,继续重复这个过程。

是否该使用递归的最主要的判断条件就是递归的规模,他决定了递归所要花费的时间和空间。

而判断递归的规模最重要的是知道这个递归的究竟是在减小问题的规模,还是维持问题的规模,还是在扩大问题的规模。

如果这个递归是在减小问题的规模,比如是最常见呈几何级数减小,那么这个递归就是好的递归。因为这样,我们的递归次数可以保持在对数级别。这样无论问题的规模有多大,都不用担心。

如果递归不能够减小问题的规模,甚至会扩大问题的规模,那么就该寻找迭代这种更为合适的解决方法。


对于分析递归的时间复杂度,有两种比较好用的方法,一种是主方法,一种是画递归树。而递归的空间复杂度,则取决于递归的深度。通常来讲,每次递归需要的空间大小是局部变量大小+参数大小+1个字长的返回地址+一个字长的上一栈的栈底,用这个基数乘以递归的次数,就是递归所需要的空间。


主方法的使用范围有限,不过大部分常用递归都可以通过主方法一眼看出答案。

主方法的定义是针对

t(n)=at(n/b)+f(n)

把log以b为底的a的对数和f(n)的复杂度比较。如果前者大,复杂度就是n**log(a,b)

如果相等,就是n**log(a,b)lgn

如果小,就是f(n)

当然这并不是严格定义了,只是一个简单的理解。用于做一个直觉的判断。


另外,如果递归只是出于数学目的,求递归的值,类似上次举的求和的例子,完全可以通过数学的方法来解决,比如用生成函数的方法求出通项公式。通过通项公式,用O(1)的复杂度就可以把问题解决。唯一不爽的是,很多情况下,通项公式的系数往往含有无理数,只能用近似的方法求值,导致算法可能未必得到精准的答案。