題目來源:牛客網-劍指Offer專題
題目地址:斐波那契數列
題目描述
大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項爲0)。n<=39
題目解析
方法一:
普通遞歸版求法,這種方法通常和漢諾塔一起被放在課本的遞歸教學部分,應該是面試官不希望看到的算法。
利用上面遞推式,自頂向下進行求解,因爲存在大量的重疊子問題,時間複雜度爲 。
public class Solution {
public int Fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
方法二:
我們可以將遞推式的求解從自頂向下改爲自底向上(循環實現)。簡而言之,我們已知前兩項的值,然後我們就可以用前兩項的值求出第3項的值,接着求第4、第5、……,直到求出第n項的值。(廢話)
實現過程如下圖所示,兩個相同顏色的箭頭可以確定一個新的數列項。
上述算法的時間複雜度爲 ,在面試中夠用了,如果還是覺得簡單可以繼續往下看。
public class Solution {
public int Fibonacci(int n) {
if (n == 0) {
return 0;
}
int a = 1, b = 1;
for (int i = 1; i <= n - 2; i++) {
a = a + b;
b = a - b;
}
return a;
}
}
方法三:
我們知道:
將其轉化成矩陣運算可得
而右邊的階矩陣又可以進一步分解爲
按照這樣一直分解下去直到右邊的階矩陣F(2),F(1),即
這時利用矩陣版的快速冪求解其中的矩陣冪乘,就可以在 的時間複雜度下得出Fibonacci數列的第n項的值。
這種方法通常是用在算法比賽中,在面試中容易裝逼失敗不適合使用,這裏也不掛板子了。
方法四:
根據上面的遞推式,利用我們高中學過的“待定係數法”可以推導出斐波那契數列的通項公式。公式如下,(推導過程略)
公式法時間複雜度爲 ? 感覺不然,求公式中的 次方應該要用上快速冪,我個人認爲時間複雜度應該也是 。(我要滾去看源碼了 )
public class Solution {
public int Fibonacci(int n) {
double a = Math.sqrt(5)/5;
double b = Math.pow((1+ Math.sqrt(5))/2, n);
double c = Math.pow((1- Math.sqrt(5))/2, n);
return (int)(a * (b - c));
}
}
後記:
如果你在寫出循環版之後,再給面試官描述後面兩種算法,並流暢寫出通項公式的推導過程,相信肯定可以取得面試官的芳心~
如果本文對你有所幫助,要記得點贊哦~