在講述遞迴演算法時,有乙個經典的例子——斐波拉契數列。
在數學上,斐波拉契數列有兩種描述,一是描述過程:
二是描述結果:
程式設計師考察的重點是前者, 如何有**描述這一過程。這裡記錄三種求解過程。
遞迴是乙個函式在內部呼叫自身。在解決由許多相同小問題組成的大問題時,遞迴有著簡潔的優點,從寫**和分析問題本身來說,遞迴是不錯的選擇。但是如果你要兼顧到程式的效率問題,迴圈就比遞迴好太多了。
斐波拉契數列是乙個典型的遞迴問題,它的每一項都是前兩項之和,用遞迴的思想很容易求出數列的第n項。
上圖是用遞迴計算斐波拉契數列第五項的過程,可以看到fi(1)被計算了兩次,fi(2)被計算了3次,fi(3)被計算了兩次。如果要計算第100項、1000項,這中間的重複計算就很可觀了,而且每次計算都有函式呼叫過程,中間也有不少的時間和空間消耗,導致了遞迴的效率不高。遞迴深度過大時經常會有棧溢位的現象。
遞迴的思路是自上而下的求解過程,迴圈是自下而上的求解過程。先求第一項,再求第二項,然後第三項……直到第n項。
int fibonacci(int index)
return result;
}
如果你是在參加一場面試,那麼這個答案也多半是面試官期待看到的答案。還請記住,使用迴圈計算斐波拉契數列的時間複雜度是o(n)。
斐波拉契數列還有乙個非常神奇的性質:
利用這個公式可以通過求
來求解數列的第n項。
此外還可以利用乘方性質進一步簡化計算。
}這個演算法的時間複雜度是o(logn),但實際上這個演算法在計算時花的時間並不會比迴圈少。總而言之,裝逼而不實用。
在實際面試中,常常會拐彎抹角的考到斐波拉契數列,當看到這類題目時,要能反應過來這是在考斐波拉契數列。
傳說中有乙隻青蛙和其他所有青蛙都不一樣,因為它是乙隻懂得斐波拉契數列的青蛙。它要跳上n級台階,但是它每次只能跳上一級或兩級台階(看心情),然後讓你算它一共有多少種跳法。
這是乙個典型的斐波拉契數列問題。如果你倒著想,它最後一次跳上第n級台階有幾種情況呢。要麼從第n-1級台階跳上去,要麼從第n-2級台階跳上去。所以跳上第n級台階的跳法總數就是跳上第n-1級台階和跳上第n-2級台階的總數之和。也就是:
f(n) = f(n-1) + f(n + 1)。
然而還有一種成為神的青蛙,它們不受地心引力的影響,可以一次跳上任意級台階,現在它要跳上n級台階總共有多少種跳法呢。其實思路和上面是一樣的,只不過現在跳上第n級台階的跳法等於跳上第n-1、n-2、n-3、……2、1級台階的跳法總和。於是:
f(n) = f(n-1) + f(n-2) + f(n-3) + ··· + f(2) + f(1)
f(n-1) = f(n-2) + f(n-3) + f(n-4) + ··· + f(2) + f(1)
兩式相減得到:
f(n) = 2f(n-1)
這是個等比公式,通項為
另外乙個例子是用乙個2*1的小矩形去覆蓋2*n的大矩形,問有多少種覆蓋方法。
考慮n=0時的情況,一定是0;
考慮n=1時的情況,有1種覆蓋方法——豎著;f(1) = 1;
考慮n=2時的情況,有2種覆蓋方法——豎著和橫著;f(2) = 2;
考慮n=n時的情況,如果豎著放,右邊還剩下2*(n-1)個矩形,也就是有f(n-1)種放法,如果橫著放,右邊還剩下2*(n-2)個矩形,也就是有f(n-2)種放法。
雖然不是標準的斐波拉契數列,但是依然是同樣的求解方法。
斐波拉契數列
斐波拉契數列 1 1 2 3 5 8 13 21 34.其中每乙個數字都是前兩個數字的和。遞迴計算 long fibonacci int n 非遞迴計算 long fibonacci int n return result 這個函式的遞迴實現使用了雙重遞迴 double recursion 函式對本...
斐波拉契數列
編寫彙編程序列印1 1000的斐波拉契數列 原始碼assume cs code,ss stack,ds data data segment fibo dw 0,1,64 dup 0 str db the fibo list is 0ah,0dh,data ends stack segment db ...
斐波拉契數列
斐波拉契數列 這個數列從第三項開始,每一項都等於前兩項之和。已知斐波拉契數列的前兩項都是1,我們定義求斐波拉契數列的第n項 n 50 的函式為fbnq,請補充完成對fbnq函式的定義。輸入格式 共一行,為乙個正整數。輸出格式 共一行,為乙個正整數。輸入樣例 7輸出樣例 13 斐波拉契數列 def f...