斐波纳契数列(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
斐波那契数列: 在数学上它以递归的方式进行定义,指这样的一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……,即前两个数为分别为0和1...本例为LabVIEW中编写递归VI实现求解斐波那契数列Fib(n)中第n项的值
使用函数求fibonacci数,根据需求词本文列举了三种主流思想包括递归、迭代和动态规划的思路介绍和算法代码实现。
用迭代的方法 寻找第N项的斐波那契数列 C语言下测试可用
已知斐波那契数列 F n =F n−1 +F n−2 (n>=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>=2,n∈N*)在现代物理、准晶体结构、...
分别采用矩阵相乘法(分治递归)和直接累加求和的方法求解第n个斐波那契数
利用递归数列求解著名的Fibonacci数列的各项,用户可自定义输入要求的第n项,输入后即可求出从0到n每一项Fibonacci的值。
算法4利用斐波那契数列递推公式的特性,只保留了每个元素的当前值和它前面的2个元素值,对计算过程中产生的子问题解用过即弃,所需空间较少,但每次求解新元素的值,都需
动态规划(Dynamic Programming,简称DP)算法是一种通过将问题划分为相互重叠的子问题,并解决子问题来解决原问题的方法。它通常用于优化问题,其中需要找到最优解或最大/最小值。动态规划算法的核心思想在于将复杂...
该脚本提供了不确定性的最终区间,其中单变量非线性/线性函数的最小值。 该函数在区间内应该是单峰的。 该脚本检查函数的单峰性。用户输入初始间隔和迭代次数。... 该算法基于斐波那契数列 1 1 2 3 5 8 13....
//使用递归计算指定位数的斐波那契数列值 //Fn=F(n-1)+F(n-2) public static int GetFibonacciNumber(int index) { if(index<0||index==0)throw new Exception(“参数不能小于或等于0”); if(index<=2)...
动态规划(Dynamic Programming)是一种将复杂问题分解为相对简单的子问题,借助子问题的解来求解原问题的优化算法。它通过记录已解决的子问题的解,避免重复计算,从而提高算法的效率。下面是一个动态规划实现示例的说明...
这是本人上学期间,使用用c++的方法求斐波那契数列,对于入门级轻松上手。
如果大家对这个生僻的术语不理解的话,那就先听小编给大家说个现实生活中的实际案例吧,...练习:使用递归和非递归的方法来求解斐波那契数列的第 n 项 代码如下: # _*_coding:utf-8_*_ def fibnacci(n): if n == 1
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. 暴力解法习题 暴力解法往往是最直观、最...
经典的例子包括计算阶乘、斐波那契数列等。递归虽然精炼,但需要注意避免无限递归以及递归深度过深导致的性能问题。 掌握这些概念对于理解和编写程序至关重要,它们可以帮助你构建具有复杂逻辑的程序,并有效地解决...