第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
原文地址:https://www.cnblogs.com/gaopeng527/p/4623514.html