`

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

 
阅读更多

    斐波纳契数列(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时时间消耗。

 

算法真是程序的灵魂。

 

分享到:
评论

相关推荐

    用循环算法求解斐波那契数列

    用循环算法求解斐波那契数列,里面有详细代码文件,亲测可运行

    算法设计实验报告之多种方法求解斐波那契数列

    用递推算法 迭代算法 公式法计算求第N个Fibonacci数,计算机能算出最大Fibonacci时N的值,计算1分钟内能计算几个Fibonacci,用公式法计算Fibonacci,当出现错误时,N为多少。

    Java实现用递归算法和非递归算法求解斐波那契数列问题.docx

    Java实现用递归算法和非递归算法求解斐波那契数列问题.docx

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

    斐波那契数列: 在数学上它以递归的方式进行定义,指这样的一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……,即前两个数为分别为0和1...本例为LabVIEW中编写递归VI实现求解斐波那契数列Fib(n)中第n项的值

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

    使用函数求fibonacci数,根据需求词本文列举了三种主流思想包括递归、迭代和动态规划的思路介绍和算法代码实现。

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

    用迭代的方法 寻找第N项的斐波那契数列 C语言下测试可用

    斐波那契数列的代码实现

    已知斐波那契数列 F ​n ​​ =F ​n−1 ​​ +F ​n−2 ​​ (n&gt;=3),F ​1 ​​ =1,F ​2 ​​ =1 用递归的方法求解该数列的第n项。 输入格式: 输入一个正整数n (1)。 输出格式: 输出一个数,数列的第n项 输入...

    斐波那契数列的求解

    斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n&gt;=2,n∈N*)在现代物理、准晶体结构、...

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

    分别采用矩阵相乘法(分治递归)和直接累加求和的方法求解第n个斐波那契数

    利用递归函数求解Fibonacci数列

    利用递归数列求解著名的Fibonacci数列的各项,用户可自定义输入要求的第n项,输入后即可求出从0到n每一项Fibonacci的值。

    动态规划专题之斐波那契数列1

    算法4利用斐波那契数列递推公式的特性,只保留了每个元素的当前值和它前面的2个元素值,对计算过程中产生的子问题解用过即弃,所需空间较少,但每次求解新元素的值,都需

    动态规划算法入门指南:从斐波那契数列到爬楼梯问题

    动态规划(Dynamic Programming,简称DP)算法是一种通过将问题划分为相互重叠的子问题,并解决子问题来解决原问题的方法。它通常用于优化问题,其中需要找到最优解或最大/最小值。动态规划算法的核心思想在于将复杂...

    斐波那契搜索法:该函数使用斐波那契数列查找函数最小值所在的区间。-matlab开发

    该脚本提供了不确定性的最终区间,其中单变量非线性/线性函数的最小值。 该函数在区间内应该是单峰的。 该脚本检查函数的单峰性。用户输入初始间隔和迭代次数。... 该算法基于斐波那契数列 1 1 2 3 5 8 13....

    基于使用递归推算指定位数的斐波那契数列值的解决方法

     //使用递归计算指定位数的斐波那契数列值 //Fn=F(n-1)+F(n-2) public static int GetFibonacciNumber(int index) { if(index&lt;0||index==0)throw new Exception(“参数不能小于或等于0”); if(index&lt;=2)...

    动态规划c++实现的demo

    动态规划(Dynamic Programming)是一种将复杂问题分解为相对简单的子问题,借助子问题的解来求解原问题的优化算法。它通过记录已解决的子问题的解,避免重复计算,从而提高算法的效率。下面是一个动态规划实现示例的说明...

    斐波那契.cpp

    这是本人上学期间,使用用c++的方法求斐波那契数列,对于入门级轻松上手。

    python动态规划算法实例详解

    如果大家对这个生僻的术语不理解的话,那就先听小编给大家说个现实生活中的实际案例吧,...练习:使用递归和非递归的方法来求解斐波那契数列的第 n 项 代码如下: # _*_coding:utf-8_*_ def fibnacci(n): if n == 1

    算法设计与分析PPT(C语言完整版)

    3.4.4斐波那契数列的应用 3.4.5递推关系求解方程 习题 第三篇核心篇 第4章基本的算法策略4.1迭代算法 4.1.1递推法 4.1.2倒推法 4.1.3迭代法解方程 4.2蛮力法 4.2.1枚举法 4.2.2其他范例 4.3分治算法 4.3.1分治算法...

    暴力、递归与分治、动态规划、贪心算法、回溯经典习题

    暴力、递归与分治、动态规划、贪心算法和回溯是算法设计中常见的几种思路和方法,经典习题是帮助我们更好掌握这些算法思想的重要途径。以下是对这些经典习题的详细说明: 1. 暴力解法习题 暴力解法往往是最直观、最...

    控制语句、方法、递归算法(二)

    经典的例子包括计算阶乘、斐波那契数列等。递归虽然精炼,但需要注意避免无限递归以及递归深度过深导致的性能问题。 掌握这些概念对于理解和编写程序至关重要,它们可以帮助你构建具有复杂逻辑的程序,并有效地解决...

Global site tag (gtag.js) - Google Analytics