`

求解斐波拉契数列的几种算法

 
阅读更多

    斐波纳契数列(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实现用递归算法和非递归算法求解斐波那契数列问题.docx

    ### Java实现用递归算法和非递归算法求解斐波那契数列问题 #### 知识点解析 在给定的文档标题与描述中,“Java实现用递归算法和非递归算法求解斐波那契数列问题”明确指出了本文将围绕Java编程语言、递归算法与非...

    编写函数f,功能是用递归的方法求斐波那契数列的第n项

    【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,...

    利用函数求解斐波那契数列的主流三种算法介绍与代码实现.md

    ### 利用函数求解斐波那契数列的主流三种算法介绍与代码实现 #### 一、引言 斐波那契数列是一个经典的数学序列,在计算机科学领域有着广泛的应用,例如算法优化、数据结构设计等。该数列定义为:F(0) = 0,F(1) = ...

    Labview实现递归:斐波那契数列

    斐波那契数列: 在数学上它以递归的方式进行定义,指这样的一个数列: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&gt;=3),F ​1 ​​ =1,F ​2 ​​ =1 用递归的方法求解该数列的第n项。 输入格式: 输入一个正整数n (1)。 输出格式: 输出一个数,数列的第n项 输入...

    用C语言求解斐波那契数列的前n项并输出及兔子繁殖问题.docx

    在C语言中,求解斐波那契数列通常有几种方法,包括递归、动态规划、循环等。在这个例子中,我们使用了一个简单的循环结构配合switch语句来计算斐波那契数列的前n项。首先,定义一个大小为n的整型数组f来存储每一项的...

    斐波那契数列及其性质

    斐波那契数列,又称为兔子数列,是由意大利数学家斐波那契提出的一种数列模式。这个数列的定义是通过一个简单的递推公式实现的:每一项都是前两项的和。数列的前几项是1、1、2、3、5、8、13、21、34、55……。...

    迭代斐波那契额数列C语言

    在C语言中,实现斐波那契数列可以通过两种主要方法:递归和迭代。本案例中,我们关注的是迭代方法,它通常比递归更高效,因为递归可能导致大量的重复计算。 迭代法的基本思路是使用两个变量来存储前两项的值,然后...

    简单K阶斐波那契数列程序

    斐波那契数列是一个经典的数学概念,它在计算机科学中有着广泛的应用,尤其是在算法设计、数据结构和问题解决等领域。K阶斐波那契数列是这一概念的拓展,通常我们所说的斐波那契数列是二阶的,即F(0) = 0,F(1) = 1...

    斐波那契数列求和_whyadm_斐波那契求和c_数列求和_poorbv2_

    在压缩包"斐波那契数列求和"中,可能包含了以上提到的几种算法的实现代码,通过阅读和分析这些代码,可以进一步学习和实践这些概念和技术。标签"whyadm"、"斐波那契求和c"、"数列求和"和"poorbv2"可能是作者或项目...

    斐波那契数列详解

    因此,数学家们发展出了多种求解斐波那契数列的高效方法。 一种常见的方法是利用特征方程来求解,这涉及到了线性代数的概念。斐波那契数列的线性递推关系可以转化为一个二次方程X^2 = X + 1。解这个方程得到两个...

    斐波那契数列求解(矩阵相乘、直接累加)

    针对斐波那契数列的求解,有两种主要方法在给定的文件中被提及:矩阵相乘法和直接累加法。 1. **矩阵相乘法**: 这种方法利用了矩阵快速幂的性质来高效地求解斐波那契数列。我们可以将斐波那契数列的生成规则表示...

    斐波拉契数列

    在C++中,实现斐波那契数列的方法主要有以下几种: 1. **迭代法**: 这是最直接且效率较高的方法。通过两个变量保存前两个数,然后不断更新这两个变量的值,直到计算到指定的项数。这种方法的时间复杂度为O(n),...

    算法-斐波那契数列(信息学奥赛一本通-T1159)(包含源程序).rar

    通过阅读和分析这些源代码,可以加深对斐波那契数列算法的理解,并提高编程能力。 在信息学奥赛中,解决斐波那契数列问题不仅能锻炼选手的逻辑思维和编程技巧,还能培养他们对算法优化和复杂度分析的敏感性,这对...

    几种求广义斐波那契数列的Matlab实现方法.zip

    这个压缩包文件"几种求广义斐波那契数列的Matlab实现方法.pdf"可能包含了上述方法的详细解释和示例,供学习者参考。通过阅读和理解这些内容,你将能够更好地掌握如何在Matlab中求解广义斐波那契数列,并能够根据实际...

    JAVA代码]斐波那契数列GUI

    例如,斐波那契数列的前几项是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 ...

Global site tag (gtag.js) - Google Analytics