用python写出斐波那契数列,编程求斐波那契数列前20项python

  用python写出斐波那契数列,编程求斐波那契数列前20项python

  0.问题描述

  在数学上,用斐波那契数来表示。

  ),称为斐波那契数列。这个数列中的每一个数都等于排在它前面的两个数之和。从系列0和1开始:

  ,

  序列中第n个(n1)的编号如下

  根据上面的公式,计算得到的斐波那契数列如下。

  随着n的增加,斐波那契数列的增长比逐渐接近黄金分割比。

  本文尝试用递归方法:时间复杂度,三种不同时间复杂度的算法,来求解数列的第n个数。

  循环:时间的复杂性

  矩阵乘法:时间复杂度

  (?有讨论的余地)

  1.递归解

  根据斐波那契数列的计算公式:

  在中选择所需的族。自然,这个问题适合用递归方法来解决。下面是直接的python代码。

  effib _ recurve(n):

  If=1: # basecase递归终止条件

  返回

  向下返回Fib _ recurve(n-1)Fib _ recurve(n-2)#递归

  时间复杂性分析

  细心的读者应该能观察到,递归求解的过程就像构建二叉树一样。例如,解开

  依赖关系

  和

  我们现在

  作为树的根节点,

  和

  继续向下递归,以左节点为左右叶节点。

  继续分解成

  和

  ,右节点

  继续分解成

  和

  在中选择所需的族。如下图所示。

  因此,算法的时间复杂度。

  性能优化

  指数复杂度太高

  长响应时间是不可接受的,但是有优化的空间。从上面的二叉树可以看出,有很多重复的节点。优化方法是将计算结果存储在字典中,每次都调查字典中是否已经存在相同的节点。如果存在,则直接返回,否则将新节点存储在字典中。优化的步骤如下。

  Dic={} #字典

  def fib _ recurve _ with _ DIC(n):

  全局dic #使用外部变量,这些变量必须首先声明。

  If=1: # basecase递归终止条件

  返回

  在dic中查找n:# dictionary

  返回到DIC [n]

  否则未找到:#

  result=fib _ recur _ with _ DIC(n-1)fib _ recur _ with _ DIC(n-2)fib _ recur _ with _ DIC))).

  DIC [n ]=结果#存储结果

  返回结果

  优化后的程序相当于修剪了之前的递归树。因为同一个节点只执行一次,所以降低了时间复杂度。

  2.循环解

  假设前面的递归解法是从上到下把一个大问题分解成小问题,那么循环解法的规律就是逆向思维。自下而上,先求出小问题的解,再进一步求出最终问题的解。

  求解过程如下

  单击将每个步骤的结果保存到列表中与下标相对应的位置。代码如下所示。

  effib_loop(n):

  IFN=1: # 0,1直接返回

  返回

  Fib=[0] * (n 1) #初始化数组

  fibs[1]=1

  for range(2,n 1): #从下标为2的数字开始

  fibs[i]=fibs[i-1] fibs[i-2]

  Return fibs[n] #返回第n个数

  时间复杂性分析

  单一周期,时间复杂性

  在中选择所需的族。它与最优化的递归解具有相同的复杂性。

  性能优化

  时间复杂度没有优化的余地,但是可以用两个。

  临时变量被替换为长度

  列表,这样空间复杂度就从

  减少到。代码如下:

  def fib_loop_nolist(n):

  如果=1: # 0,1直接返回

  返回

  a,b=0,1

  对于范围(2,n-1)中的I:#从2开始

  a,b=b,a b

  返回b

  3.矩阵连续乘法

  根据斐波那契数列本身的性质,我们可以构造如下等式关系:

  用矩阵来表达上述方程关系,即

  因此

  依次向下乘,得到一般形式。

  我们寻求解决方案。

  是矢量。

  的第一部分。代码如下:

  将numpy作为np导入

  def fib_matrix(n):

  如果=1: # 0,1直接返回

  返回

  result=np.mat([[1,1],[1,0]],dtype= float 64 )* *(n-1)* NP . mat([1,0])。T

  return int(结果[0,0])

  时间复杂性分析

  从程序的角度来看,result结果几乎都是由一条语句返回的,所以时间复杂度为。但是语句涉及到幂运算,也就是N个矩阵相乘,时间复杂度好像是。这个结论值得商榷。

  性能优化

  矩阵对角化后,乘法运算可以大大提高运算效率。对角化的方法是

  ,其中

  是要对角化的矩阵,

  经过

  由特征向量组成的矩阵,

  经过

  由的特征值组成的对角矩阵。

  ,python代码如下:

  将numpy作为np导入

  定义纤维矩阵诊断(n):

  如果=1: # 0,1直接返回

  返回

  A=np.array([[1,1],[1,0]])

  E=np.linalg.eig(A) # E保存A的特征值和特征向量。

  D=np.diag(E[0]) #特征值对角矩阵

  S=E[1] #特征向量矩阵

  result=NP . mat(S)* NP . mat(D)* *(n-1)* NP . mat(NP . linalg . inv(S))* NP . mat([1,0])。T

  return int(结果[0,0])

  问题

  NumPy在处理矩阵乘法时会做很多浮点运算,在

  当为时,结果的准确性会丢失。

  4总结经过实际运行测试,无字典递归算法在

  几乎慢到无法使用。

  使用字典优化的递归算法与循环算法具有相同的性能,使用

  测试的运行时间约为十分之一秒。

  矩阵乘法算法虽然看似简单,但运行效率不如循环算法,运行时间约为千分之一秒,矩阵并没有给求解运算带来明显的性能提升。

  运营效率最终排序为:循环法。

  递归(带字典)

  矩阵连续乘法

  递归(无字典)。

  涉及

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: