Computational Complexity of Fibonacci Sequence / 斐波那契数列的时空复杂度

Posted yexuesong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Computational Complexity of Fibonacci Sequence / 斐波那契数列的时空复杂度相关的知识,希望对你有一定的参考价值。

Fibonacci Sequence 维基百科

(F(n) = F(n-1)+F(n-2)),其中 (F(0)=0, F(1)=1),即该数列由 0 和 1 开始,之后的数字由相邻的前两项相加而得出。

递归

def fibonacci(n):
    assert n >= 0, 'invalid n'
    if n < 2: return n
    return fibonacci(n - 1) + fibonacci(n -2)

递归方法的时间复杂度为高度为 (n-1) 的不完全二叉树的节点数,所以近似为 (O(2^n))

数学求解方法:

(T(n) = T(n-1) + T(n-2) qquad (n>1))

(f(n)) 为参数为 n 时的时间复杂度 (f(n) = f(n-1) + f(n-2))

转化为求二阶常系数齐次差分方程,设通解为 (f_{n} = C_{1}f_{n-1} + C_{2}f_{n-2})

设有特解 (f_{n} = lambda)(lambda) 为非零待定常数,将 (lambda) 代入方程,易得特征方程 (lambda ^{2} = lambda + 1),则 (λ = frac{1pm sqrt{5}}{2})

再根据 (f(0) = 0, f(1) = 1.) 求出 (C_{1})(C_{2})

得出通项公式

[ f(n) = frac{1}{sqrt{5}}[(frac{1+ sqrt{5}}{2})^{n} - (frac{1- sqrt{5}}{2})^{n}] ]

(n->infty) 时, (left |(frac{1- sqrt{5}}{2})^{n} ight |<1),所以趋于零。

时间复杂度为 (O((frac{1+ sqrt{5}}{2})^{n})) ,约等于 (O(1.618^{n})) ,即指数级复杂度 (O(2^n)),递归算法空间复杂度取决于递归的深度,显然为 (O(n))

迭代

def fibonacci(n):
    assert n >= 0, 'invalid n'
    if n == 0: return 0
    a, b = 0, 1 
    for _ in range(n - 1): 
        a, b = b, a+b
    return b

时间复杂度 (O(n)),空间复杂度 (O(1))

矩阵

(F(n))(F(n - 1)) 写成一个 2 x 1 的矩阵,然后对其进行变形。

(egin{bmatrix}F_{n}F_{n-1}end{bmatrix}=egin{bmatrix}F_{n-1}+F_{n-2}F_{n-1}end{bmatrix}=egin{bmatrix}1 imes F_{n-1}+1 imes F_{n-2}1 imes F_{n-1}+0 imes F_{n-2}end{bmatrix}=egin{bmatrix}1 & 1 1 & 0end{bmatrix} imesegin{bmatrix}F_{n-1}F_{n-2}end{bmatrix}=...=egin{bmatrix}1&11&0end{bmatrix}^{n-1} imesegin{bmatrix}F_{1}F_{0}end{bmatrix}=egin{bmatrix}1&11&0end{bmatrix}^{n-1} imesegin{bmatrix}1end{bmatrix})

因此要求 (F_{n}),只要对这个二阶方阵求 (n - 1) 次方,最后取结果方阵第一行第一列的数字就可以了。

等式中的矩阵 (egin{bmatrix}1&11&0end{bmatrix}) 被称为斐波那契数列的 Q- 矩阵。

通过 Q- 矩阵,我们可以利用如下公式进行计算:

(F_{n} = Q^{n-1}_{1,1})

如此一来,计算斐波那契数列的问题就转化为了求 (Q^{n-1}) 的问题。

[ A^{n} = egin{cases} Acdot (A^{2})^{frac{n-1}{2}}, & ext{if $n$ is odd} (A^{2})^{frac{n}{2}}, & ext{if $n$ is even} end{cases} ]

可见时间复杂度满足 (T(n) = T(n / 2) + O(1))
Master 定理 可得

时间复杂度 (O( log n)) ,空间复杂度显然为 (O(1))

from numpy import matrix
 
def MatrixPower(mat, n):
    assert n > 0, 'invalid n'
    res = None
    temp = mat
    while True:
      if n & 1:
        if res is None: res = temp
        else: res = res * temp
      n >>= 1
      if n == 0: break
      temp = temp * temp
    return res
 
def fibonacci(n):
    assert n >= 0, 'invalid n'
    if n < 2: return n  # F(0) = 0, F(1) = 1
    mat = matrix([[1, 1], [1, 0]], dtype=object)
    mat = MatrixPower(mat, n - 1)
    return mat[0, 0]

通项公式法

技术图片

技术图片

def fibonacci(n):
    root_Five = 5**0.5
    result = (((1 + root_Five) / 2)**n - ((1 - root_Five) / 2)**n) / root_Five
    return int(result)

显然,该方法的时空复杂度均为 (O(1)) , 但使用公式计算的方法由于有大量的浮点运算,在 n 增大时浮点误差不断增大会导致返回结果不正确甚至数据溢出。

方法 时间复杂度 空间复杂度
递归 (O(2^{n})) (O(n))
迭代 (O(n)) (O(1))
矩阵 (O(log^{n})) (O(1))
公式 (O(1)) (O(1))

以上是关于Computational Complexity of Fibonacci Sequence / 斐波那契数列的时空复杂度的主要内容,如果未能解决你的问题,请参考以下文章

Computational Complexity of Fibonacci Sequence / 斐波那契数列的时空复杂度

CITS1401 Computational

CSC1002 – Computational Laboratory

Computational Finance with C++

MATH4/60082 (Computational Finance)

ELEE 5400/440 - Computational Intelligence Techniques