python 斐波那契數列 演算法

2021-10-16 12:14:49 字數 2788 閱讀 4192

斐波那契數,通常用f(n)表示,形成的序列稱為 斐波那契數列 。該數列由 0 和 1 開始,後面的每一項數字都是前面兩項數字的和。也就是:

f(0) = 0,f(1) = 1

f(n) = f(n - 1) + f(n - 2),其中 n > 1

給你 n ,請計算 f(n) 。

示例 1:

輸入:2

輸出:1

解釋:f(2) = f(1) + f(0) = 1 + 0 = 1

遞迴有兩個基本要素:基例以及遞迴關係式。

def

fib(n)

:#base case

if n <=1:

return n

elif n >=2:

return fib(n-1)

+ fib(n-

2)

然後根據python語法特性,可以縮寫為一句話

def

fib(n)

:return fib(n-1)

+ fib(n-2)

if n >=

1else n

f(20) = f(19)+f(18)

f(19) = f(18)+f(17)

然後我們發現 f(18) 重複,即冗餘結構。這樣的運算時間會很大,

節點數 * 每個子問題所需要的時間 = 時間複雜度

顯而易見,這種情況下為o(2^n)

純遞迴的缺點就在於存在過多冗餘結構。

遞迴加記憶,將指數級時間將為多項式級時間。

我們可以將已經出現計算好的存在乙個備忘錄裡面,這樣我們下一次計算之前,先去查一遍表就行,不需要再重新計算。

memo =

deffib

(n):

#查表if n in memo:

return memo[n]

#base case:

elif n <=1:

return n

else

: ans = fib(n-1)

+ fib(n-2)

memo[n]

= ans

return memo[n]

當然,上述的備忘錄既可以採用陣列,同時也可以用雜湊表。

另外,如果追求完美一點,可以將基例儲存到備忘錄裡面,這樣可以減少一定程度的空間複雜度。

memo =

這裡介紹的是由上而下的方法,當然也可以是由下而上的。雖然比純遞迴好,但是時間複雜度依然很高,leetcode上為1500-1600ms左右。

bottem-up-solution

def

fib(n)

: memo =

for i in

range(2

,n+1):

memo[i]

= memo[i-1]

+ memo[i-2]

return memo[n]

for迴圈的左邊是因為備忘錄裡面已經有鍵0,1了,所以從2開始。然後我們最後要計算的是memo[n],i = n 所以要為n+1

這個的時間複雜度會大大降低,兩者看似都是查表,但是由下而上的這種不會重新迭代函式,只會不斷計算表。leetcode資料為36ms

演算法方面的優化到此為止,但是關於空間複雜度可以更優化一點,

import sys

h =l =[0

,1]print

(sys.getsizeof(h)

)print

(sys.getsizeof(l)

)#232

#72

字典的空間複雜度遠大於列表,所以可以更優化一點。單方面來講,複雜度跟元素大小無關。跟元素個數有關。

def

fib(n)

:if n ==0:

return

0 memo[

1for i in

range

(n+1)]

memo[0]

,memo[1]

=0,1

for i in

range(2

,n+1):

memo[i]

= memo[i-1]

+ memo[i-2]

return memo[n]

關於第一行生成len = n+1的原因,因為最後返回索引為n,而索引從0開始

而且除了列表生成器的表達,還可以

memo = [1] * (n+1)

之所以提取生成長度為n+1的列表,是為了防止列表索引不夠,進行有序的替換。

因為是替換的,所以初始化列表的值是任取的,只要保證基例正確就行。

要小心的是,如果輸入0沒有開頭的if語句是會報錯的(for 迴圈)

還有就是力扣的很多時候判別的不准,大家只要往死裡優化,看看幾個最優解就行。不必苛求100%,大家可以複製幾個100%,有些是運氣100%,到你這就不是100%

最後,作為拓展,還有一種滾動變數的方法。

def

fib(n)

:if n ==0:

return

0for i in

range

(n):

a,b = b,a+b

return a

這種方法顯然不是最優解,但是值得一說的是,按照一些書中python的**規範。這種結構可讀性不好,建議少用。

大家覺得好的話,可以去github上給我點小星星呦

斐波那契數列 斐波那契數列python實現

斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...

Python演算法 斐波那契數列

典型的遞迴演算法 快速排序會用到 先做個鋪墊 斐波那契數列即著名的兔子數列 1 1 2 3 5 8 13 21 34 數列特點 該數列從第三項開始,每個數的值為其前兩個數之和,用python實現起來很簡單 定義fibonacci數列如下 非遞迴方法的函式實現 def fibs num result ...

Python斐波那契數列演算法

第一種 函式求裴波那契數列 def func num if n 1 or n 2 如果n等於1或者2 return 1 返回1 else 否則 return func n 1 func n 2 返回函式n 1加上函式n 2的值 print func 12 輸出第12個裴波那契數列的數第二種 用類求裴...