斐波那契数列算法优化问题

本文探讨了斐波那契数列在编程中的优化算法,包括递归、循环迭代、矩阵算法及其快速幂优化,以及通项式直接求解等方法,并通过测试比较了各种方法的效率。矩阵快速幂算法在处理大项数时表现优越。
摘要由CSDN通过智能技术生成

斐波那契是数学中最值得讨论的一个问题,从12世纪斐波那契提出这个数列后,就有很多数学家研究过这个数列,对斐波那契数列的新发现也越来越多,这些细节我没能力去研究,这篇文章中要讲的是编程中对生成斐波那契数算法的优化。首先要说的就是斐波那契数列的定义,这一切都起源于一个生殖能力超强的兔子:

  • 第一个月初有一对刚诞生的兔子
  • 第二个月后(第三个月初)他们可以生育
  • 每月没对兔子可生育的兔子会诞生下一对新兔子
  • 兔子永不死去

几乎每个学计算机的在学编程语言的时候都会遇到这样的习题:计算第N个月兔子的总数

点击这里查看完整源代码,建议对着完整的代码调试。

最简单的递归算法

老师肯定会教的一种方法:

uint64_t fibonacci(unsigned int n) {
    if (n == 0) return 0;
    if (n <= 2) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

该方法来自于斐波那契数列的一个递推式:fib(n) = fib(n-1) + fib(n-2)

然后使用递归算法并指定递归出口,即可得出结果。

使用循环迭代消除递归

递归因为要不断地调用函数自身,调用函数就伴随着参数以及函数局部变量入栈,当递归层数较大容易产生栈溢出,所以通常需要我们使用循环优化递归算法。幸运地是,大多数递归都能修改成循环(使用自定义栈保存变量的方式仍然算递归)。而且上面的算法在效率上存在很大的优化空间:

斐波那契数列

你会发现fib(5) = fib(4) + fib(3),而求fib(4)的时候我们已经求过fib(3),这意味着我们做了很多重复的工作,很明显我们需要把前面做过的工作暂存。

递归算法时间呈指数形式增长:O(2^N);而使用循环迭代时间上呈线性增长:O(N)。在我笔记本上测试时,当n超过40递归算法的时间就开始爆炸了。

uint64_t fibonacci(unsigned int n) {
    if (n == 0) return 0;
    if (n == 1 || n == 2) return 1;
    uint64_t f1 = 1, f2 = 1, fn;
    for (unsigned int i = 3; i <= n; i++) {
        fn = f1 + f2;
        f1 = f2;
        f2 = fn;
    }
    return fn;
}

矩阵算法求解

斐波那契数列的递推公式是:fib(n) = fib(n-1) + fib(n-2);我们可以用矩阵来表示这种关系:

[FnFn1]=[Fn1Fn2Fn1]=[1110]×[Fn1Fn2] [ F n F n − 1 ] = [ F n − 1 − F n − 2 F n − 1 ] = [ 1 1 1 0 ] × [ F n − 1 F n − 2 ]

进一步推到可以得到:
[FnFn1]=[1110]n1×[F1F0]=[1110]n1×[10] [ F n F n − 1 ] = [ 1 1 1 0 ] n − 1 × [ F 1 F 0 ] = [ 1 1 1 0 ] n − 1 × [ 1 0 ]

从0开始算得到Fn则需要更进一步:

[Fn+1Fn]=[1110]n×[F1F0]=[1110]n×[10] [ F n + 1 F n ] = [ 1 1 1 0 ] n × [ F 1 F 0 ] = [ 1 1 1 0 ] n × [ 1 0 ]

我们要实现一下矩阵运算:

[a00a10a01a11]×
  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值