• 第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
  • 相关阅读:
    我国主机遭境外控制激增近80%
    NSOperation 详解
    NSOperation 详解
    Bitmap的recycle问题
    Bitmap的recycle问题
    NSDate 格式化含有毫秒
    NSDate 格式化含有毫秒
    CSS长度单位:px和pt的区别
    CSS长度单位:px和pt的区别
    Object-c学习笔记十八-----NSPredicate
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4623514.html
Copyright © 2020-2023  润新知