Fibonacci数列,我想有的人在大学甚至高中就已经接触过了,其数学表达如下:
给定一正整数x,
F(x) = 1 ( x=1 或 x=2)
F(x) = F(x-1) + F(x-2) ( x > 2 )
也就是说,前2个数是1, 后面的的数, 是前面2个数之和
如果用计算机来解决的话, 可有递归和非递归算法, 对于递归算法很好理解, 也很好实现,直接照着上面的公式来就行了, 下面是递归算法的c语言实现:
|
可以看见,代码非常的简单,也很好理解,然而, 这个效率是极其低下, 我试图打印前50个数, 结果发现程序运行了近2分钟才返回,打印的越多, 运行的越慢, 所耗费的时间成级数增长。有关这个递归算法的时间复杂度计算:
T(1) = 1
T(2) = 2
T(N) = T(N-1)+ T(N-2)
求解T(N)的过程会用到高数中的通项公式,我基本忘完了了。
不过我在《数据结构与算法分析-c语言描述》看到,可以使用归纳法推导出:(3/2)^n<T(N)<(5/3)^n
我搜索到网上的结果为(1.618)^n,说明这个是以某个指数级增长的。
参考网址:http://zhidao.baidu.com/question/63335536.html
下面是非递归算法,非递归的算法的思想其实也很简单:如果你要计算第N个数,只需要循环N次,每次用两个数来记录第N-1和N-2个数,因为第N个
数只是和它前面两个数有关系,和其他数据没有关系。
时间复杂度却是O(n)。而且同样打印前面50个数, 只用了1秒钟, 可见,这个差别是多么的巨大。 下面是非递归算法的c语言代码:
|
可以将时间复杂度降低为logN,我暂不考虑,因为数学很久不碰,很多东西都忘了。
总结几点结论:
1.递归的方法并非不好,之所以这个Fibonacci数列用递归方式计算,效率不高,是因为他
有重复的计算。计算第N个值时要计算第N-1,N-2个值,计算第N+1个值时,要计算第N,N-1
个值,每个值重复计算了。在其他很多情况下,使用递归,效率是很高的。
2.递归的代码清晰简洁,容易让人看懂,但是递归函数,递归的次数太多,会增加很多
堆栈的开销,增加空间复杂度。
3.算法的改良,主要在于思想的转变,多想想用什么方式可以做得更好。
4.时间复杂度的计算,矩阵算法,都必须把数学学好。