首页 > 其他分享 >探秘斐波那契数列:如何在0.02毫秒内计算21亿

探秘斐波那契数列:如何在0.02毫秒内计算21亿

时间:2024-08-04 15:23:52浏览次数:16  
标签:数列 0.02 复杂度 矩阵 long 斐波 那契

针对斐波那契数列算法进行详细介绍和优化,从最简单的递归方法到更高效的迭代、缓存、动态规划、公式推导和矩阵解法,最终达到了时间复杂度为O(logn)的快速幂矩阵解法来感受算法的神奇之处,最后可以看到如何实现在输入n=2100000000(21亿)时仅耗时0.02毫秒的最佳效果。

一、回顾斐波那契数列

斐波那契数列(Fibonacci sequence)是一种非常经典的数学序列,其特点是每个数字是前两个数字之和,起始于0和1。也就是说,数列的第三个数是前两个数的和,第四个数是第二个数和第三个数的和,以此类推。斐波那契数列的前几项是:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

这个数列最早是意大利数学家斐波那契(Fibonacci)在其《算盘书》(1202年)中引入的,用来描述兔子繁殖的理想化情况。假设一对刚出生的兔子一年后成熟并能生育,且从第二年开始每年产下一对新兔子,不考虑其他因素的影响。这个问题导致了斐波那契数列的产生,兔子的对数就对应了斐波那契数列的每一项。

那通过算法实现求第n个斐波那契数的具体数值,让我们感受下算法的不断优化和极致表现。

二、矩阵解法+快速幂解法分析

基本思想是利用矩阵乘法的性质,将斐波那契数列的递推关系表示为矩阵形式,然后通过快速幂算法来快速计算矩阵的高次幂,从而得到斐波那契数列的第n项的值。

三、代码展示

package org.zyf.javabasic.algorithm;
 
/**
 * @program: zyfboot-javabasic
 * @description: 使用矩阵解法结合快速幂
 * @author: zhangyanfeng
 * @create: 2024-04-25 01:06
 **/
public class MatrixFibonacciWithFastPower {
    private static final long[][] INIT_MATRIX = {{1, 1}, {1, 0}};
    private static final long[][] UNIT_MATRIX = {{1, 0}, {0, 1}};
 
    public static long getFibonacciByMatrixAndFastPower(int index) {
        // 检查索引的有效性
        if (index <= 0) {
            throw new IllegalArgumentException("Index must be a positive integer");
        }
 
        // 边界情况处理
        if (index == 1 || index == 2) {
            return 1;
        }
 
        // 初始结果为单位矩阵
        long[][] result = UNIT_MATRIX;
        long[][] temp = INIT_MATRIX;
        int m = index - 2;
 
        // 利用快速幂算法计算矩阵的高次幂
        while (m != 0) {
            if ((m & 1) == 1) {
                result = matrixMultiply(temp, result);
            }
            temp = matrixMultiply(temp, temp);
            m >>= 1;
        }
 
        // 结果矩阵的第一个元素即为斐波那契数列的第n项的值
        return result[0][0];
    }
 
    // 矩阵乘法
    private static long[][] matrixMultiply(long[][] a, long[][] b) {
        long[][] result = new long[2][2];
        result[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
        result[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
        result[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
        result[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
        return result;
    }
 
    public static void main(String[] args) {
        // 计算第100000项的斐波那契数
        long startTime1 = System.nanoTime();
        long fibonacci100000 = MatrixFibonacciWithFastPower.getFibonacciByMatrixAndFastPower(100000);
        long endTime1 = System.nanoTime();
        double elapsedTime1 = (endTime1 - startTime1) / 1_000_000.0; // 转换为毫秒
        System.out.println("Fibonacci(100000) = " + fibonacci100000);
        System.out.println("耗时:" + elapsedTime1 + "毫秒");
 
        // 计算第2100000000项的斐波那契数
        long startTime2 = System.nanoTime();
        long fibonacci2100000000 = MatrixFibonacciWithFastPower.getFibonacciByMatrixAndFastPower(2100000000);
        long endTime2 = System.nanoTime();
        double elapsedTime2 = (endTime2 - startTime2) / 1_000_000.0; // 转换为毫秒
        System.out.println("Fibonacci(2100000000) = " + fibonacci2100000000);
        System.out.println("耗时:" + elapsedTime2 + "毫秒");
    }
}

四、性能分析

时间复杂度分析:计算第n项斐波那契数需要进行快速幂运算,时间复杂度为O(log n)。这是因为快速幂算法的时间复杂度为O(log n),在算法中只需进行log n次乘法运算。在快速幂运算中,每次矩阵相乘的时间复杂度为O(1)。因此,总的时间复杂度为O(log n)。
空间复杂度分析:算法中使用的空间主要由两个矩阵所占用的空间决定。这两个矩阵分别是初始矩阵和结果矩阵,都是固定大小的2x2矩阵。因此,空间复杂度为O(1),即常数级别的空间复杂度。
实际运行发现当n为10万时耗时0.013125毫秒,n为21亿时耗时0.022042毫秒。

矩阵解法结合快速幂的斐波那契数列算法具有优秀的时间复杂度O(log n)和空间复杂度O(1),适用于需要高效计算大数值斐波那契数列的场景。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/xiaofeng10330111/article/details/138143503

标签:数列,0.02,复杂度,矩阵,long,斐波,那契
From: https://blog.csdn.net/m0_74022416/article/details/140906547

相关文章

  • 极限性能:21亿斐波那契数列在0.02毫秒内计算完成
    针对斐波那契数列算法进行详细介绍和优化,从最简单的递归方法到更高效的迭代、缓存、动态规划、公式推导和矩阵解法,最终达到了时间复杂度为O(logn)的快速幂矩阵解法来感受算法的神奇之处,最后可以看到如何实现在输入n=2100000000(21亿)时仅耗时0.02毫秒的最佳效果。一、回顾斐波......
  • 代码随想录day32 || 509斐波那契数列 70爬楼梯 746使用最小花费爬楼梯
    509斐波那契数列力扣题目链接题目描述:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:F(0)=0,F(1) =1F(n)=F(n-1)+F(n-2),其中n>1给定 n ,请计算 F(n) 。代码1......
  • 为什么 functools.cache 装饰器不能在我的带有记忆功能的斐波那契序列函数上工作?
    我在python中搞乱了记忆,并使用了一个示例斐波那契序列函数作为模型。我将第一个fibonacci()函数编写为常规函数,无需记忆,它按预期工作。接下来,我编写了我的fibonacci_memo()函数,该函数使用带有输出的输入字典来利用记忆化,并且按预期工作。然后我想测试functo......
  • 编写并测试Fibonacci()函数,该函数用循环替代递归计算斐波那契数
    /编写并测试Fibonacci()函数,该函数用循环替代递归计算斐波那契数斐波那契数列(FibonacciSequence)又称黄金分割数列。特别指出:第0项是0,第1项是第一个1。此数列从第2项开始,每一项都等于前两项之和。/include<stdio.h>intFibonacci(intn){//使用循环计算斐波那契数inta=0,b......
  • 【数论】1 矩阵快速幂(斐波那契)
    Tips:本篇blog适合刚开始学习数论部分的同学本题解仅代表个人思路,如有异议欢迎批评指正,谢谢一.概述该章节讲述的是矩阵运算及快速幂的概念,学过的同学可以跳过本章,直接看矩阵快速幂1.矩阵矩阵类似于向量,我们可以这么来表示一个矩阵如上图,表示了一个  的矩阵。矩阵也......
  • 代码随想录 day33 斐波那契数 | 爬楼梯 |使用最小花费爬楼梯
    斐波那契数斐波那契数解题思路利用代码随想录给出的解题模板进行解题。先确定dp数组和dp下标的含义,之后需要确定遍历的顺序,接着我们通过枚举获得遍历的规矩,最后确定dq的初始值。知识点动态规划心得第一次做动态规划,主要是掌握基本的解题思路,了解一下到底是怎么解决问题的......
  • 函数传参,递归函数(汉诺塔,裴波那契数列),预处理
    递归函数 获得斐波那契数列的第n项的值斐波那契数列是指这样一个数列:1,1,2,3,5,8,13,21,34,55,89……这个数列从第3项开始,每一项都等于前两项之和。#include<stdio.h>intFbnq(intn){if(n==1){return1;}elseif(n==2){return1......
  • 代码随想录算法训练营第35天 | 动态规划1:509.斐波那契数、70.爬楼梯、746.使用最小花
    代码随想录算法训练营第35天|动态规划理论基础https://programmercarl.com/动态规划理论基础.html#算法公开课509.斐波那契数https://leetcode.cn/problems/fibonacci-number/submissions/548309803/代码随想录https://programmercarl.com/0509.斐波那契数.html#算法公开......
  • 【c语言】函数递归的一些例题1.编写一个函数,不许创建临时变量,求字符串长度 2.求n的阶
    1.intmy_strlen(char*str){   if(*str!='\0')   {      return1+my_strlen(str+1);//利用递归求字符串长度:递归一次就是多一个字符这样就可以求出字符串的长度了   }   else      return0;}intmain(){   //编写......
  • 闲话 7.12 - 斐波拉契拆分
    贺自论文《FIBONACCIPARTITIONS》,这个证明略去了一些繁而不难的分类讨论,感兴趣的(?)可以前往原论文查看。根据欧拉五边形数定理,有:\[\prod_{i\ge1}(1-x^i)=1+\sum_{k\ge1}(-1)^kx^{k(3k\pm1)}\]这也是在\(S=\N\)集合的拆分中,奇数互异的拆分和偶数互异拆分的差值。这样的差......