以最快的速度求出Fibonacci 序列的第n項

題目:定義Fibonacci序列如下:f(0)=0,f(1)=f(2)=1,n>2時,f(n)=f(n-1)+f(n-2) ,輸入n ,用最快的方法求該數列的第 n 項。

分析:

       首先遞歸求法肯定都會,但是由於遞推關係的形式,很容易看出裏面有很多的重複計算。改進的方法也很容易想到,即申請額外的兩個空間來存放保存前面的計算結果,以此來提供速度:

參考代碼:

1: int getNthFibonacci(int n) 
2: {  
3:     int first=0,second=1;  
4:     if(n==0 || n==1)  
5:         return n;   
6: 
7:     int result=0;   
8:     for(int i=1;i<n;i++)  
9:     {  
10:         result += first+second;
11:         first=second;  
12:         second=result;  
13:     } 
14:     return result;  
15: }

這裏時間複雜度爲O(n),網上還有一種時間複雜度爲log(n)的算法,思想如下:

其數學基礎:方陣{ f(n), f(n-1), f(n-1), f(n-2) } = {1, 1, 1,0 }n-1

即前者表示一個2X2的方陣,後者表示一個第一行爲1,1、第二行爲1,0的方陣的n-1次方。矩陣{1,1,1,0}的n-1次方的結果的第一行第一列就是f(n),可以用歸納法證明,比較簡單。

現在的問題轉換爲求矩陣{1, 1, 1, 0}的乘方。如果簡單第從0開始循環,n次方將需要n次運算,並不比前面的方法要快。但我們可以考慮乘方的如下性質:

        /   an/2*an/2                      n爲偶數時 
an
        \  a(n-1)/2*a(n-1)/2              n爲奇數時

要求得n次方,我們先求得n/2次方,再把n/2的結果平方一下。如果把求n次方的問題看成一個大問題,把求n/2看成一個較小的問題。這種把大問題分解成一個或多個小問題的思路我們稱之爲分治法。這樣求n次方就只需要logn次運算了。

參考代碼:

1: #include<stdlib.h> 
2: #include<stdio.h>  
3: #include<string.h> //memcpy  
4:   
5: void multiply(int A[], int B[], int result[])   
6: {  
7:     result[0] = A[0]*B[0] + A[1]*B[2];  
8:     result[1] = A[0]*B[1] + A[1]*B[3];  
9:     result[2] = A[2]*B[0] + A[3]*B[2];
10:     result[3] = A[2]*B[1] + A[3]*B[3]; 
11: }  
12:  
13: void power(int A[], int n, int result[]) 
14: {  
15:     if (n==1)  
16:     {  
17:         memcpy(A, result, 4*sizeof(int));  
18:         return;  
19:     }  
20:     int tmp[4];
21:     power(A, n>>1, result); 
22:     multiply(result, result, tmp);  
23: 
24:     if (n & 1 == 1)  
25:     {  
26:         multiply(tmp, A, result); 
27:     }   
28:     else  
29:     { 
30:         memcpy(result, tmp, 4*sizeof(int));  
31:     }  
32: }  
33:  
34: int getNthFibonacci(int n)  
35: {  
36:     int A[4] = {1,1,1,0};
37:     int result[4]={1,1,1,0}; 
38:     power(A, n, result);
39:  
40:     return result[0]; 
41: }  
42:   
43:  
44: int main()  
45: {  
46:int n
47:     while(scanf("%d",&n)) 
48:     { 
49:         if(n==-1) 
50:             break;  
51:         if(n==0 || n==1)  
52:             printf("n=%d,result=%d\n",n,n); 
53:         else  
54:             printf("n=%d,result=%d\n",n,getNthFibonacci(n-1));
55:     } 
56:     getchar(); 
57:     return 0; 
58: }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章