fibnacci數列1,1,2,3,5,8,13,21...,數列第一項和第二項等於1,從第三項開始開始,每一項都等於前兩項之和,簡單的用數學公式表示:
n=0或n=1時,f(n)=1;
n>1時,f(n) = f(n-1) + f(n-2)
可以看出使用遞迴演算法可解決該問題,python**如下:
def fibnacci_i(x):
if x < 0:
return 0
if x == 0 or x == 1:
return 1
return fibnacci_i(x-1) + fibnacci_i(x-2)
執行fibnacci_i(20),結果為10946。似乎一切正常。但是當x的值很大時,程式會出現執行錯誤:runtimeerror: maximum recursion depth exceeded,最大遞迴深度溢位,這是因為python中遞迴深度大於等於1000時就會報錯。即使python不做限制,當x很大時,程式需要耗費很長的時間才能計算完成,這裡就涉及到linux堆疊的問題。因為linux系統為計算機分配的堆疊大小有限制(使用ulimit -a可檢視堆疊大小),而程式執行時會將程式放入堆疊,每呼叫一次遞迴就會分配一次堆疊,乙個堆疊的大小為8k,我的虛擬機器的堆疊大小為8092k,可以看出很快就會把堆疊用盡,所以時間複雜度就很大。該演算法的時間複雜度為o(2^n)。
仔細看fibnacci數列,可以發現有很多重複運算,比如f(5) = f(4) + f(3);f(4) = f(3) + f(2);這裡對f(3)做了重複計算,那麼可以對演算法做改進,將重複的計算結果快取起來,用空間來換取時間。改進後的程式**如下:
cache =
def fibnacci_ii(x):
global cache
if x < 0:
return 0
if x == 0 or x == 1:
return 1
if x in cache:
return cache[x]
result = fibnacci_ii(x-1) + fibnacci_ii(x-2)
if x not in cache:
cache[x] = result
return result
實際執行一下可以看出改進後的程式比原有程式效率高很多。因為對中間結果做了儲存,所以實際上是用空間來換取時間。
似乎已經很好了,還有更好的解法嗎?答案是肯定的,使用迴圈可將演算法改進為非遞迴演算法,因為f(x) = f(x-1) + f(x-2),那麼我們可以在計算f(x-1)和f(x-2)時將結果儲存下來,那麼計算f(x)的時候就可以直接得到結果了,依次類推,可以用乙個for迴圈解決。該演算法的**如下:
def fibnacci_iii(x):
if x < 0:
return 1
if x == 0 or x == 1:
return 1
result = 0
a = 1
b = 1
for i in xrange(x):
if i > 1:
result = a + b
a = b
b = result
return a + b
總結,遞迴演算法的特點是清晰明了,但是遞迴演算法的時間複雜度很大,意味著計算時間會很長,而改為非遞迴演算法後,可以很好的減少時間複雜度。寫程式時應該盡量避免遞迴,將遞迴演算法改為非遞迴演算法。 fibnacci數列遞迴實現
斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家萊昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 0 1 1 2 3 5 8 13 21 34 在數學上,斐波那契數列以如下被以遞推的方法定義 f ...
fibnacci數列遞迴實現
1.斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家萊昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 0 1 1 2 3 5 8 13 21 34 在數學上,斐波那契數列以如下被以遞推的方法定義 ...
fibnacci數列遞迴實現
1.網上查詢資料說明什麼是fibnacci數列?答 斐波那契數列 fibonacci sequence 又稱 分割數列 兔子數列,是數學家列昂納多 斐波那契於1202年提出的數列。斐波那契數列為1 1 2 3 5 8 13 21 34 此數列從第3項開始,每一項都等於前兩項之和。2.給出fibnac...