斐波纳契数列(Fibonacci Sequence),在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。
求解Fibonacci第N项的值有几种方法,本文详细写出几种算法的实现,并验证算法的执行时间。
1、递归法
这是一种最直接的方法,从他的定义中可以直接得出,代码也很简单,如下:
//普通的递归算法 T(n) = T(n-1) + T(n-2) //指数级的时间复杂度 public static long fiWithRecursion(int n){ if ( n == 0) return 0; else if ( n == 1) return 1; else return fiWithRecursion(n - 1) + fiWithRecursion(n - 2); }
从递归式,我们可以简单的猜到,求解T(N),需要先求解T(N-1)和T(N-2),算法复杂度是指数级的,原因就是计算T(N)的时候,没有很好利用中间的计算结果,导致重复计算。
2、迭代法
迭代法通过2个中间变量,循环迭代N次,算法复杂度为线性的。
//采用迭代算法 //线性时间复杂度O(n) public static long fiWithIterator(int n){ if ( n == 0) return 0; if ( n == 1) return 1; long f0 = 0; long f1 = 1; for(int i = 2; i<= n ; i++){ long temp = f0; f0 = f1; f1 = temp + f1; } return f1; }
3、分治法
分治法利用矩阵的乘法来实现,使时间复杂度降到O(lgN),思想来源于神书《算法导论》,的确佩服算法的设计者,不说直接上全部代码。
package com.xx.dataStructure; public class Fi { final static int [][] BASEMATRIX = {{1,1},{1,0} }; //普通的递归算法 T(n) = T(n-1) + T(n-2) //指数级的时间复杂度 public static long fiWithRecursion(int n){ if ( n == 0) return 0; else if ( n == 1) return 1; else return fiWithRecursion(n - 1) + fiWithRecursion(n - 2); } //采用迭代算法 //线性时间复杂度O(n) public static long fiWithIterator(int n){ if ( n == 0) return 0; if ( n == 1) return 1; long f0 = 0; long f1 = 1; for(int i = 2; i<= n ; i++){ long temp = f0; f0 = f1; f1 = temp + f1; } return f1; } //采用分治法的矩阵运算 //对数的时间复杂度O(lgN) public static long fiWithMatrix(int n){ if ( n == 0) return 0; if ( n == 1) return 1; int [][] data = recruit(n); return data[0][1]; } private static int [][] recruit(int n){ if (n == 1) return BASEMATRIX; else if (n % 2 == 0){ int [][] data = recruit(n/2); return matrixTimes(data,data,2); }else { int [][] data = recruit((n-1)/2); return matrixTimes(matrixTimes(data,data,2),BASEMATRIX,2); } } //分治法计算x^n public static int mm(int n,int x){ if ( n == 0) return 1; if ( n == 1) return x; else if ( n % 2 == 0){ return mm(n/2,x) * mm(n/2,x); } else { return mm((n-1)/2,x) * mm((n-1)/2,x) * x ; } } //计算矩阵乘法 private static int [][] matrixTimes(int [][] a, int [][] b,int n){ int [][] c = new int[n][n]; for(int i =0; i< n ; i++){ for(int j =0; j< n ; j++){ for(int k = 0; k< n ; k++){ c[i][j] += a[i][k] * b[k][j]; } } } return c; } /** * @param args */ public static void main(String[] args) { //0,1,1,2,3,5,8,13,21,34,55 Long begin2 = System.nanoTime(); fiWithRecution(15); Long end2 = System.nanoTime(); System.out.println("user recure argrithom: 【" + (end2 - begin2) + "ns】"); Long begin1 = System.nanoTime(); fiWithIterator(1500000); Long end1 = System.nanoTime(); System.out.println("user iterator argrithom: 【" + (end1 - begin1) + "ns】"); Long begin3 = System.nanoTime(); fiWithMatrix(1500000); Long end3 = System.nanoTime(); System.out.println("user matrix argrithom: 【" + (end3 - begin3) + "ns】"); } }
程序执行结果如下:
user recure argrithom: 【161931ns】
user iterator argrithom: 【3665696ns】
user matrix argrithom: 【79255ns】
可见采用递归法求解N=15时消耗的时间就已经超过使用矩阵乘法分治求解N=1500000时时间消耗。
算法真是程序的灵魂。
相关推荐
在这个算法设计实验报告中,主要关注的是通过不同的方法求解斐波那契数列,这是一种经典的计算机科学问题。斐波那契数列是由0和1开始,后面的每一项数字是前面两项数字的和,通常表示为F(n)。实验的目标是实现四种...
用循环算法求解斐波那契数列,里面有详细代码文件,亲测可运行
### Java实现用递归算法和非递归算法求解斐波那契数列问题 #### 知识点解析 在给定的文档标题与描述中,“Java实现用递归算法和非递归算法求解斐波那契数列问题”明确指出了本文将围绕Java编程语言、递归算法与非...
【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,...
### 利用函数求解斐波那契数列的主流三种算法介绍与代码实现 #### 一、引言 斐波那契数列是一个经典的数学序列,在计算机科学领域有着广泛的应用,例如算法优化、数据结构设计等。该数列定义为:F(0) = 0,F(1) = ...
斐波那契数列: 在数学上它以递归的方式进行定义,指这样的一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……,即前两个数为分别为0和1...本例为LabVIEW中编写递归VI实现求解斐波那契数列Fib(n)中第n项的值
已知斐波那契数列 F n =F n−1 +F n−2 (n>=3),F 1 =1,F 2 =1 用递归的方法求解该数列的第n项。 输入格式: 输入一个正整数n (1)。 输出格式: 输出一个数,数列的第n项 输入...
在C语言中,求解斐波那契数列通常有几种方法,包括递归、动态规划、循环等。在这个例子中,我们使用了一个简单的循环结构配合switch语句来计算斐波那契数列的前n项。首先,定义一个大小为n的整型数组f来存储每一项的...
斐波那契数列,又称为兔子数列,是由意大利数学家斐波那契提出的一种数列模式。这个数列的定义是通过一个简单的递推公式实现的:每一项都是前两项的和。数列的前几项是1、1、2、3、5、8、13、21、34、55……。...
在C语言中,实现斐波那契数列可以通过两种主要方法:递归和迭代。本案例中,我们关注的是迭代方法,它通常比递归更高效,因为递归可能导致大量的重复计算。 迭代法的基本思路是使用两个变量来存储前两项的值,然后...
斐波那契数列是一个经典的数学概念,它在计算机科学中有着广泛的应用,尤其是在算法设计、数据结构和问题解决等领域。K阶斐波那契数列是这一概念的拓展,通常我们所说的斐波那契数列是二阶的,即F(0) = 0,F(1) = 1...
在压缩包"斐波那契数列求和"中,可能包含了以上提到的几种算法的实现代码,通过阅读和分析这些代码,可以进一步学习和实践这些概念和技术。标签"whyadm"、"斐波那契求和c"、"数列求和"和"poorbv2"可能是作者或项目...
因此,数学家们发展出了多种求解斐波那契数列的高效方法。 一种常见的方法是利用特征方程来求解,这涉及到了线性代数的概念。斐波那契数列的线性递推关系可以转化为一个二次方程X^2 = X + 1。解这个方程得到两个...
针对斐波那契数列的求解,有两种主要方法在给定的文件中被提及:矩阵相乘法和直接累加法。 1. **矩阵相乘法**: 这种方法利用了矩阵快速幂的性质来高效地求解斐波那契数列。我们可以将斐波那契数列的生成规则表示...
在C++中,实现斐波那契数列的方法主要有以下几种: 1. **迭代法**: 这是最直接且效率较高的方法。通过两个变量保存前两个数,然后不断更新这两个变量的值,直到计算到指定的项数。这种方法的时间复杂度为O(n),...
通过阅读和分析这些源代码,可以加深对斐波那契数列算法的理解,并提高编程能力。 在信息学奥赛中,解决斐波那契数列问题不仅能锻炼选手的逻辑思维和编程技巧,还能培养他们对算法优化和复杂度分析的敏感性,这对...
这个压缩包文件"几种求广义斐波那契数列的Matlab实现方法.pdf"可能包含了上述方法的详细解释和示例,供学习者参考。通过阅读和理解这些内容,你将能够更好地掌握如何在Matlab中求解广义斐波那契数列,并能够根据实际...
例如,斐波那契数列的前几项是0, 1, 1, 2, 3, 5, 8, 13, 21, 34等。在编程中,实现斐波那契数列可以用于理解和练习递归、动态规划等概念。 在这个名为"JAVA代码]斐波那契数列GUI"的项目中,开发者创建了一个图形...
在编程中,解决斐波那契数列通常有以下几种方法: 1. **递归**:最直观的方法,但效率较低,因为它会产生大量的重复计算。C#代码如下: ```csharp public int Fibonacci(int n) { if (n ) return n; else ...