[算法学习]斐波那契数的计算

决定开始看algorithms,而且尽量多思考,多写点代码。第一个碰到的算法就很具有启发性,一些看似正确的算法,实际的复杂度却很高。我们直接看问题:


问题:假设fibonacci(0)=0,fibonacci(1)=1,如果计算fibonacci(n)

解决方案一:直接利用斐波那契数的性质用递归计算

1  def  fibonacci1(n):
2       if  n  ==  0:
3           return  0
4       elif  n  ==   1 :
5           return   1
6       else :
7           return  fibonacci1(n - 1 ) + fibonacci1(n - 2 )

一看好像这样做没什么不妥,但是你如果跑下fibonacci1(50)机器就开始忙碌了,仔细想想,这个算法的复杂度其实是O(2n),看看原书上的图就明白了


其中重复的计算很多,最后需要计算的次数是20.694n +3n次,这个明显是不行的,当n较大时,什么电脑都要跑上很久很久

解决方案二:不用递归,直接用循环计算

1  def  fibonacci2(n):
2      fib = [0,  1 ]
3       for  i  in  range( 2 ,n + 1 ):
4          fib.append(fib[i - 1 ] + fib[i - 2 ])
5       return  fib[n]

这种做法也比较直观,很明显这种方法的复杂度是O(n)。一般来说,你肯定会觉得这样就够了,实际上还有logn复杂度的方法。

解决方案三:用矩阵计算

斐波那契数的性质可以用矩阵来表示:,那么有。我们用X来表示其中的0111矩阵,那么对于Fn,我们只要计算Xn

就可以得到Fn。当然我们不能用循环来计算Xn ,而是用“折半法“通过Xn/2 *Xn/2计算。

ExpandedBlockStart.gif 代码
 1  def  fibonacci3(n):
 2       return  recuCal(n)[ 1 ]
 3 
 4  matrix = [0, 1 , 1 , 1 ]
 5  def  recuCal(n):
 6       if  n  ==   1 :
 7           return  matrix
 8       elif  n  ==   2 :
 9           return  matrixCal(matrix,matrix)
10       elif  n  %   2 :
11           return  matrixCal(matrixCal(recuCal(n / 2 ),recuCal(n / 2 )),matrix)
12       else :
13           return  matrixCal(recuCal(n / 2 ),recuCal(n / 2 ))
14 
15  def  matrixCal(matrix1,matrix2):
16      matrix3  =  [0,0,0,0]
17      matrix3[0] = matrix1[0] * matrix2[0] + matrix1[ 1 ] * matrix2[ 2 ]
18      matrix3[ 1 ] = matrix1[0] * matrix2[ 1 ] + matrix1[ 1 ] * matrix2[ 3 ]
19      matrix3[ 2 ] = matrix1[ 2 ] * matrix2[0] + matrix1[ 3 ] * matrix2[ 2 ]
20      matrix3[ 3 ] = matrix1[ 2 ] * matrix2[ 1 ] + matrix1[ 3 ] * matrix2[ 3 ]
21       return  matrix3

算法比较简单,matrixCal是计算两个矩阵的方法。recuCal是实现“折半法”的函数,返回计算结果矩阵,而这个矩阵的第2个数就是需要的结果。


以上代码都是用python写的,可以再写一个main来验证结果:

1  if   __name__   ==   ' __main__ ' :
2       print  fibonacci1( 50 )
3       print  fibonacci2( 50 )
4       print  fibonacci3( 50 )

当然fibonacci1(50)短时间跑不完的。最好还是把n定小点。

写完咯,睡觉

 

转载于:https://www.cnblogs.com/kakafei/archive/2009/12/04/1616576.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值