第2章 数字之魅——斐波那契(Fibonacci)数列

斐波那契(Fibonacci)数列

问题描述

递归算法:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * Fibonacci数列递归求解
 4  * @author DELL
 5  *
 6  */
 7 public class Fibonacci1 {
 8     public static int fibonacci(int n){
 9         if(n<=0)
10             return 0;
11         else if(n==1)
12             return 1;
13         else
14             return fibonacci(n-1)+fibonacci(n-2);
15     }
16     public static void main(String[] args) {
17         int n = 3;
18         System.out.println("fibonacci("+n+") = "+fibonacci(n));
19
20     }
21
22 }

我们的问题是:有没有更加优化的解法?

分析与解法

【解法一】递推关系的优化

上述递归算法中有着很多的重复计算,利用一个数组存储中间结果避免重复计算。时间复杂度为O(N),空间复杂度也为O(N)。

算法如下:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * Fibonacci数列求解
 4  * 【解法一】递推关系的优化
 5  * @author DELL
 6  *
 7  */
 8 public class Fibonacci2 {
 9     private static int f[];
10     public Fibonacci2(int n){
11         f = new int[n+1];
12         for(int i=0;i<n;i++){
13             f[i]=-1;
14         }
15     }
16     public static int fibonacci(int n){
17         if(n<=0){
18             f[0]=0;
19             return 0;
20         }
21         else if(n==1){
22             f[1]=1;
23             return 1;
24         }
25         else{
26             if(f[n-1]==-1){
27                 if(f[n-2]==-1)
28                     return fibonacci(n-1)+fibonacci(n-2);
29                 else
30                     return fibonacci(n-1)+f[n-2];
31             }else{
32                     return f[n-1]+f[n-2];
33             }
34         }
35     }
36     public static void main(String[] args) {
37         int n = 3;
38         new Fibonacci2(n);
39         System.out.println("fibonacci("+n+") = "+fibonacci(n));
40
41     }
42
43 }

程序运行结果如下:

fibonacci(3) = 2

【解法二】采用非递归求解

算法如下:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * Fibonacci数列求解
 4  * 【解法二】非递归
 5  * @author DELL
 6  *
 7  */
 8 public class Fibonacci3 {
 9     public static int fibonacci(int n){
10         if(n<=0)
11             return 0;
12         else if(n==1)
13             return 1;
14         else{
15             int f0 = 0,f1 = 1,f2 = 0;
16             for(int i=2;i<=n;i++){
17                 f2 = f0 + f1;
18                 f0 = f1;
19                 f1 = f2;
20             }
21             return f2;
22         }
23     }
24     public static void main(String[] args) {
25         int n = 3;
26         System.out.println("fibonacci("+n+") = "+fibonacci(n));
27
28     }
29
30 }

程序运行结果如下:

fibonacci(3) = 2

【解法三】求解通项公式

算法代码如下:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * Fibonacci数列求解
 4  * 【解法三】求解通项公式
 5  * @author DELL
 6  *
 7  */
 8 public class Fibonacci4 {
 9     public static long fibonacci(int n){
10         double x = Math.sqrt(5);
11         double f = (x/5)*Math.pow((1+x)/2, n) - (x/5)*Math.pow((1-x)/2, n);
12         return Math.round(f);
13     }
14     public static void main(String[] args) {
15         int n = 3;
16         System.out.println("fibonacci("+n+") = "+fibonacci(n));
17
18     }
19
20 }

程序运行结果如下:

fibonacci(3) = 2

【解法四】分治策略

要先导入JAMA:Java矩阵包

 1 package chapter2shuzizhimei.fibonacci;
 2
 3 import Jama.Matrix;
 4
 5 /**
 6  * Fibonacci数列求解
 7  * 【解法四】分治策略
 8  * @author DELL
 9  *
10  */
11 public class Fibonacci5 {
12     //求解矩阵A的n次方
13     public static Matrix MatrixPow(Matrix A, int n){
14         int m = A.getColumnDimension();
15         Matrix result = new Matrix(m,m); //生成全为0的矩阵
16         for(int i=0;i<m;i++){  //变成单位矩阵
17             result.set(i, i, 1);
18         }
19         Matrix temp = A;
20         while(n!=0){
21             if((n&0x01)==1)
22                 result = result.times(temp);  //矩阵的乘法
23             temp = temp.times(temp);
24             n >>= 1;
25         }
26         return result;
27     }
28     //计算Fibonacci数列
29     public static long fibonacci(int n){
30         if(n<=0)
31             return 0;
32         else if(n==1)
33             return 1;
34         else{
35             Matrix A = new Matrix(2,2,1); //生成全为1的矩阵
36             A.set(1, 1, 0);
37             Matrix B = MatrixPow(A, n-1);
38             return (long) B.get(0, 0);
39         }
40     }
41     public static void main(String[] args) {
42         int n = 5;
43         System.out.println("fibonacci("+n+") = "+fibonacci(n));
44
45     }
46
47 }

程序运行结果如下:

fibonacci(5) = 5

扩展问题

  假设A(0)=1,A(1)=2,A(2)=2。对于n>2,都有A(K) = A(k-1) + A(k-2) +A(k-3)。

  1. 对于任何一个给定的n,如何计算出A(n)?

  2. 对于n非常大的情况,如n=260的时候,如何计算A(n) mod M (M<100000)呢?

问题1:非递归解法,代码如下:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * 扩展问题1求解
 4  * 非递归
 5  * @author DELL
 6  *
 7  */
 8 public class Fibonacci6 {
 9     public static int A(int n){
10         if(n<=0)
11             return 1;
12         else if(n==1||n==2)
13             return 2;
14         else{
15             int f0 = 1,f1 = 2,f2 = 2,f3 = 0;
16             for(int i=3;i<=n;i++){
17                 f3 = f0 + f1 + f2;
18                 f0 = f1;
19                 f1 = f2;
20                 f2 = f3;
21             }
22             return f3;
23         }
24     }
25     public static void main(String[] args) {
26         int n = 4;
27         System.out.println("A("+n+") = "+A(n));
28
29     }
30
31 }

程序运行结果如下:

A(4) = 9

问题2:非递归解法,代码如下:

 1 package chapter2shuzizhimei.fibonacci;
 2 /**
 3  * 扩展问题2求解
 4  * 非递归
 5  * @author DELL
 6  *
 7  */
 8 public class Fibonacci7 {
 9     //计算A(n) mod m
10     public static long A(long n,long m){
11         if(n<=0)
12             return 1;
13         else if(n==1||n==2)
14             return 2;
15         else{
16             long f0 = 1,f1 = 2,f2 = 2,f3 = 0;
17             for(int i=3;i<=n;i++){
18                 f0 = f0%m;
19                 f1 = f1%m;
20                 f2 = f2%m;
21                 f3 = f0 + f1 + f2;
22                 f0 = f1;
23                 f1 = f2;
24                 f2 = f3;
25             }
26             return f3%m;
27         }
28     }
29     public static void main(String[] args) {
30         long n = (long) Math.pow(2, 10);
31         long m = 100;
32         System.out.println("A("+n+") = "+A(n,m));
33
34     }
35
36 }

程序运行结果如下:

A(1024) = 97
时间: 2024-10-08 18:25:17

第2章 数字之魅——斐波那契(Fibonacci)数列的相关文章

编程之美 2.9 斐波那契(Fibonacci)数列

编程之美 2.9 斐波那契(Fibonacci)数列 斐波那契的递归表达式如下 F(n)=F(n-1)+F(n-2) n>=2 F(1)=1 F(0)=0 书中提到了三中解决方法 第一种:直接运用递归的方法来进行求解 package org.wrh.programbeautiful; import java.util.Scanner; public class Topic2_9 { public static void main(String[] args) { Topic2_9 t=new T

9.求斐波那契Fibonacci数列通项

(1)递归实现: #include<iostream>using namespace std;int Fibonacci(int); int main(){    int n;    cout<<"please input an number n: "<<endl;    cin>>n; for(int i=1;i<=n;i++)    {        cout<<Fibonacci(i)<<endl; 

斐波那契 [ Fibonacci] 数列之大整数求和

之前做到一题, 不过由于Honor Code的缘故就不说是啥了, 很多人都知道 (-_-) 大概是说有n个牌,每个牌只有A,B两种状态. 当出现连续3个牌的状态一样时,认为不完美. 给出一个[1, 10000]的整数, 让求出完美的排列个数 那么我们就可以分析一下: /*-------------------------------------------------------------------------------分析:    首先要求出不美观的个数,但是尝试可以发现美观的排列更容易

【编程之美】斐波那契(Fibonacci)数列

斐波那契数列是一个非常美丽.和谐的数列,有人说它起源于一对繁殖力惊人.基因非常优秀的兔子,也有人说远古时期的鹦鹉就知道这个规律. 每一个学理工科的学生都知道斐波那契数列,斐波那契数列由如下递推关系式定义: F(0)=0, F(1)=1, n>1时,F(n)=F(n-1)+F(n-2). 每一个上过算法课的同学都能用递归的方法求解斐波那契数列的第n+1项的值,即F(n). 1 int Fibonacci(int n) 2 { 3 if (n <= 0) return 0; 4 else if (

【C语言】求斐波那契(Fibonacci)数列通项(递归法、非递归法)

意大利的数学家列昂那多·斐波那契在1202年研究兔子产崽问题时发现了此数列.设一对大兔子每月生一对小兔子,每对新生兔在出生一个月后又下崽,假若兔子都不死亡.   问:一对兔子,一年能繁殖成多少对兔子?题中本质上有两类兔子:一类是能生殖的兔子,简称为大兔子:新生的兔子不能生殖,简称为小兔子:小兔子一个月就长成大兔子.求的是大兔子与小兔子的总和. 月     份  ⅠⅡ  Ⅲ  Ⅳ  Ⅴ Ⅵ  Ⅶ  Ⅷ Ⅸ Ⅹ  Ⅺ  Ⅻ大兔对数 1  1   2   3   5  8  13  21 34 55 

斐波那契 (Fibonacci)数列

尾递归会将本次方法的结果计算出来,直接传递给下个方法.效率很快. 一般的递归,在本次方法结果还没出来的时候,就调用了下次的递归, 而程序就要将部分的结果保存在内存中,直到后面的方法结束,再返回来计算.如果递归比较大,可能会照成内存溢出. 实践证明,尾递归 ,确实比普通递归效率高. 下面的例子 ,用 普通递归需要10s完成 , 而用尾递归,只用了1s不到 package com.zf.dg; /** * 题目 * 有一种母牛,出生后第三年,开始生育,每年都生一头 母牛(貌似单性生育,这里就没公牛什

如何用Python输出一个斐波那契Fibonacci数列

a,b = 0, 1 while b<100: print (b), a, b = b, a+b 原文地址:https://www.cnblogs.com/apollo1616/p/9776116.html

HDU2842之斐波那契亚数列变形,动态规划

1.原题展示: 一根棒子上有n个环(n<=10^9) 第一个环可以随意取下或者放上 如果前k个环都不在棒子上,且第k+1个环在棒子上,则你可以取下或放上第k+2个环 给出n,求最少需要多少步可以取完棒子上的环? 2.思路分析: 如果要把n个环全部拿完,那么我们必须先拿完前n-2个环(只有这样才能拿走第n个环),剩下第n-1个环未拿走.当拿走前n-2个环所花的步骤数目为f(n-2)加上最后一个环,那么所花步数为f(n-2)+1步.对于第n-1个球,如果要拿走它,必须补上前n-2个球,放进去n-2个

ACM/ICPC算法训练 之 数学很重要—斐波拉契●卢卡斯数列(HNNUOJ 11589)

看到这个标题,貌似很高大上的样子= =,其实这个也是大家熟悉的东西,先给大家科普一下斐波拉契数列. 斐波拉契数列 又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.…… 在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*) 在现代物理.准晶体结构.化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963起出版了以<斐波纳契数列季刊>为名的一份数学杂志,用于专门刊载这方面的