斐波那契數列解法

2021-09-10 07:45:57 字數 3117 閱讀 6741

1、概念

在數學上,費波那契數列是以遞迴的方法來定義:

f0=0

f1=1

fn=fn-1+fn-2(n≧2)

用文字來說,就是費波那契數列由0和1開始,之後的費波那契係數就是由之前的兩數相加而得出。首幾個費波那契係數是:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233……(oeis中的數列a000045)

特別指出:0不是第一項,而是第零項。

2、解法

2.1遞迴解法

(1)**

/*斐波那契遞迴解法*/

#include #include using namespace std;

long fibonacci(unsigned int n) else

}int main()

else

}long fibonacci(unsigned int n)

unsigned long ret=0;

//申請陣列用於儲存已經計算過的內容

unsigned long *array=(unsigned long*)calloc(n+1, sizeof(unsigned long));

if(array == null)

array[1]=1;

ret=fibonacciprocess(array,n);

free(array);

array=null;

return ret;

}

可見改進版本,時間複雜度為o(n),避免了重複計算,但是呼叫鏈仍然比較長。

2.3 迭代解法

遞迴法不夠優雅。如果不用計算機計算,讓你去算第n個斐波那契數,會怎麼做?最簡單直接的方法是:知道第乙個和第二個,計算第三個;知道第二個和第三個,計算第四個,以此類推。最終可以得到我們需要的結果。這種思路沒有冗餘的計算。**實現如下:

/*斐波那契數迭代解法*/

long fibonacciiterration(unsigned int n)

unsigned int loop=1;

unsigned long returnval=0;

while(loop < n)

return returnval;

}

時間複雜度為o(n)。

2.4 尾遞迴解法

要計算第n個斐波那契數,我們可以先先計算第乙個,第二個,如果未達到n,則繼續遞迴計算,尾遞迴實現**如下:

/*斐波那契數尾遞迴解法*/

long fibonaccitialrecursionprocess(unsigned int n, unsigned long prepreval, unsigned long preval,unsigned long begin) else

}long fibonacci(unsigned int n) else

}

尾遞迴效率並不遜於迭代法。尾遞迴在函式返回之前的最後乙個操作仍然是遞迴呼叫。尾遞迴的好處是,進入下乙個函式之前,已經獲得了當前函式的結果,因此不需要保留當前函式的環境,記憶體占用自然也是比最看是提到的遞迴要小。時間複雜度為o(n)。

2.5 矩陣快速冪解法

這是一種高效的解法,推導過程如下:

如果a為矩陣,等式同樣成立。

假設有矩陣2*2矩陣a,滿足下面的等式:

可以得到矩陣a:

因此也就可以得到下面的矩陣等式:

再進行變換如下:

以此類推,得到:

實際上f(n)就是矩a^(n-1)中的a[0][0],或者是矩a^n中的a[0][1]。

現在的問題就歸結為,如何求a^n,其中a為2*2的矩陣。根據我們最開始的公式,很容易就有思路,**實現如下:

/*矩陣快速冪解法*/

#define max_col 2

#define max_row 2

typedef unsigned long matrixtype;

//計算2*2矩陣乘法,這裡沒有寫成通用形式的矩陣乘法

int matrixdot(matrixtype a[max_row][max_col],matrixtype b[max_row][max_col],matrixtype c[max_row][max_col])

matrixtype fibonacci(int n)

matrixtype result[max_col]=;

matrixtype a[2]=;

while(n > 0)

n /= 2;

matrixdot(a,a,a);

} return result[0][1];

}

該演算法的關鍵部分在於對a^n的計算,它利用了我們開始提到的等式,對奇數和偶數分別處理。假設n為9,初始矩陣為init則計算過程如下:

·9為奇數,則計算init*a,隨後a變為a*a,n變為9/2,即為4

·4為偶數,則結果仍為init*a,隨後a變為(a2)*( a2)=a4,n變為4/2,即2

·2為偶數,則結果仍為init*a,隨後a變為(a4)*( a4)=a8,n變為2/2,即1

·1為奇數,則結果為init*(a^8)*a

可以看到,計算次數類似於二分查詢次數,其時間複雜度為o(logn)。

斐波那契數列的通項公式為:

**實現如下:

/*斐波那契數列通項公式解法*/

long fibonacci(unsigned long n)

return (unsigned long)((pow((1+sqrt(5))/2,n)-pow((1-sqrt(5))/2,n))/sqrt(5));

}

斐波那契數列解法

方法一 常規解法 def demo month 定義變數 a,b分別表示一月和二月的數目 a 0 a為第乙個數值 b 1 b為第二個數值 定義乙個計數器 i 0 while i month 列印每次的數值 print a a,b b,a b i 1 nume demo 3 方法二 函式的遞迴 def...

斐波那契數列的快速解法

求解斐波那契數列,要求時間複雜度為o logn 主要思路是快速冪和矩陣乘法的結合律 利用數學歸納法來證明。快速冪的思想 當n為偶數的時候 an an2 an2 當n為奇數的時候 an a n 1 2 a n 1 2 a那麼fn 的問題就可以換成求矩陣的n次冪了。實現 class solution p...

題目 斐波那契數列。 解法二

程式分析 斐波那契數列 fibonacci sequence 又稱 分割數列,指的是這樣乙個數列 0 1 1 2 3 5 8 13 21 34 數學上的解法是 f0 0 n 0 f1 1 n 1 fn f n 1 f n 2 n 2 我是小白,大神無笑話小弟,只是想記錄下來自己的思路,根據我自己的理...