第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

【解法三】求解通项公式

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

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

算法代码如下:

 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

【解法四】分治策略

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

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

 要先导入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

 

你可能感兴趣的:(fibonacci)