求斐波那契數列的第n項


問題描述:斐波那契數列是這樣的一個數列,1,1,2,3,5,8,..,即前兩項都是1,后面每一項都是其前面兩項的和。

              現在要你求出該數列的第n項。

分析:該問題是一個經典的數列問題,相信大家在很多語言的教科書上都碰到過這個練習題目。這里我給大家總結了三種經典解法,並對這三個方法進行了對比。

         解法一:遞歸算法。很多教科書上都用這個題作為函數遞歸知識點講解的例題,我們可以將每一個項的求法表達為這樣一個式子:

                    f(n)=f(n-1)+f(n-2),f(1)=1,f(2)=1,可以看出,可以采用遞歸算法求解。

         解法二:循環求法。我們可以從第1項開始,一直求到第n項,即可,一個循環可以做到,時間復雜度為O(n).

         解法三:矩陣鏈乘法。如果線性代數學的好的話,可以想出這樣一種解法,

                    

                         同樣可以采用遞歸的算法求解,時間復雜度為O(logn).

           三種解法對比:解法一編程最簡單,但是效率最低,因為這種遞歸算法求解時,會重復求解子問題。如下圖示:

                               

                                  這樣就看出來吧!另外如果n很大的話,遞歸的層數很大,會消耗系統大量的時間和資源。

                               解法二避免了重復求解子問題,線性時間即可求出,值得采用。

                               解法三效率最高,但是編程特別復雜,在有些情況下,很合適使用,但就本題目來說,推薦解法二。

    針對上述三種解法,我給出了詳細的Java代碼,讀者可以參考:

 1 import java.util.*;
 2 public class Main {
 3     public static int f1(int n){                     //方法一:遞歸算法,自底向上
 4         if(n<=2)return 1;                            //如果是求前兩項,直接返回就可
 5         else return f1(n-1)+f1(n-2);
 6     }
 7     public static int f2(int n){                     //方法二:循環算法,自上而下
 8         if(n<=2)return 1;                            //如果是求前兩項,直接返回就可
 9         int a1=1,a2=1,a3;
10         for(int i=3;i<=n;i++)
11             {
12               a3=a1+a2;
13               a1=a2;
14               a2=a3;
15             }
16         return a2;
17     }
18     public static int[][] f3(int n){                 //方法三:矩陣鏈相乘算法,采用遞歸實現
19         int a[][]={{1,1},{1,0}};                     //定義基矩陣
20         int b[][];                                   //存儲子方法的結果
21         int c[][]=new int[2][2];                     //存儲最后計算結果
22         int d[][]=new int[2][2];                     //存儲中間計算結果
23         if((n)<=1)return  a;                         //如果次方小等於1直接返回
24         else if((n) %2==1)
25                  {b=f3((n-1)/2);
26                 
27                  d[0][0]=b[0][0]*b[0][0]+b[0][1]*b[1][0];
28                  d[0][1]=b[0][0]*b[0][1]+b[0][1]*b[1][1];
29                  d[1][0]=b[1][0]*b[0][0]+b[1][1]*b[1][0];
30                  d[1][1]=b[1][0]*b[0][1]+b[1][1]*b[1][1];
31                 
32                  c[0][0]=d[0][0]*a[0][0]+d[0][1]*a[1][0];
33                  c[0][1]=d[0][0]*a[0][1]+d[0][1]*a[1][1];
34                  c[1][0]=d[1][0]*a[0][0]+d[1][1]*a[1][0];
35                  c[1][1]=d[1][0]*a[0][1]+d[1][1]*a[1][1];
36                  
37                 }
38         else  {
39              b=f3((n)/2);
40 
41              c[0][0]=b[0][0]*b[0][0]+b[0][1]*b[1][0];
42              c[0][1]=b[0][0]*b[0][1]+b[0][1]*b[1][1];
43              c[1][0]=b[1][0]*b[0][0]+b[1][1]*b[1][0];
44              c[1][1]=b[1][0]*b[0][1]+b[1][1]*b[1][1];
45         }
46         return c;
47     }
48     public static void main(String[] args) {
49         // TODO 自動生成的方法存根
50         Scanner scan=new Scanner(System.in);
51         int n=scan.nextInt();
52         System.out.println("方法一:"+f1(n));
53         System.out.println("方法二:"+f2(n));
54         int a[][]=f3(n-1);                            //因為是要求矩陣{{1,0},{1,0}}的n-1次方
55         System.out.println("方法三:"+a[0][0]);
56         
57     }
58 
59 }

輸出結果為:

10
方法一:55
方法二:55
方法三:55

                     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM