斐波那契額序列基本上是演算法入門繞不開的題。就好像有人想養成看書的習慣,我可能推薦他看的第一本書那就是《解憂雜貨店》。斐波那些序列這道題,不但實現方法多樣,而且更是提前讓像我這樣入門的小白,提前體會到了記憶化
和dp動態規劃
的入門思想。這這樣從易到難,從懵懂到大徹大悟的學習方法是有效果的。
題目要求如下:
現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)遞迴簡直就是為斐波那些序列的計算而設計的,所以最最最最樸素,最最最最直觀,最最最簡單的方式就是用遞迴法。而且簡單粗暴非常就兩句話就可以實現。廢話不多說直接上**。
圖1 斐波那些序列遞迴實現遞迴的實現方式算是暴力法的一種,因為它的時間複雜度是o(2n)的,這裡時間複雜度的結果並不需要用主定理,而是這個遞迴就是乙個二叉樹,每層會有兩個分支點。
其實有點接近動態規劃的方法了,動態規劃其實就是遍歷+記憶化的方式。對圖1的仔細觀察可以得知,遞迴法進行了很多的重複計算。那麼我們優化的方向也就有了,就是通過記憶化來,減少重複的計算。開闢乙個陣列nums = [0] * (n + 1),一旦計算過某個數值就將它儲存下來。每次在進行分支之前檢查下是否該數值已經被計算過了。
class
solution
:def
fibonacci
(self, n)
:def
fibonacci_m
(n, memo)
:if n <=1:
return n
ifnot memo[n]
: memo[n]
= fibonacci_m(n -
1, memo) \
+ fibonacci_m(n -
2, memo)
return memo[n]
memo =[0
]*(n +1)
return fibonacci_m(n, memo)
這樣每個數值只會被計算一次,也就起到了優化演算法的作用。那麼還有沒有更快的演算法?
喪心病狂?這還不夠嗎?還想再快點?額…其實很多演算法題是有很多反邏輯***的想法的,我覺得在面試過程裡問這些歪門邪道的優化真的都不是正常邏輯想出來的,除非你是數學家,整天研究這些。所以就當做下面這個o(logn)的演算法是從天上掉下來的吧。
下面我們看一下斐波那些序列的推導公式:
對公式進行一下矩陣轉化:
[ f(
n)f(
n−1)
]=[1
,11,
0][f
(n−1
)f(n
−2)]
=[1,
11,0
]n−1
[f(1
)f(0
)]\begin f(n) \\ f(n - 1) \end =\begin 1, 1\\ 1, 0 \end \begin f(n - 1) \\ f(n - 2) \end =\begin 1,1 \\ 1,0 \end^ \begin f(1) \\ f(0) \end
[f(n)f
(n−1
)]=
[1,1
1,0
][f(
n−1)
f(n−
2)]
=[1,
11,0
]n−
1[f(
1)f(
0)]
另m =[
1,11
,0]n
−1m=\begin 1,1 \\ 1,0 \end^
m=[1,1
1,0
]n−1
其實就等於計算:
p ow
(m,n
−1)∗
[11]
=[f(
n)f(
n−1)
]pow(m, n - 1) * \begin1\\1\end=\beginf(n) \\ f(n - 1) \end
pow(m,
n−1)
∗[11
]=[
f(n)
f(n−
1)]
其中涉及到矩陣乘法的計算,由於python從不重複造輪子,於是實現**我引入了np數值計算包,具體演算法實現如下:
def
fibonacci
(n):
m = np.array([[
1,1]
,[1,
0]])
r = np.linalg.matrix_power(m, n -1)
.dot([[
1],[
1]])
return r[
0]
斐波那契 Fibonacci 數列
實踐證明,尾遞迴 確實比普通遞迴效率高。下面的例子 用 普通遞迴需要10s完成 而用尾遞迴,只用了1s不到 package com.zf.dg 題目 有一種母牛,出生後第三年,開始生育,每年都生一頭 母牛 貌似單性生育,這裡就沒公牛什麼事兒 生出來的小母牛也符合同樣的規律,出生後第三年,開始生 育,...
Fibonacci 斐波那契數列
一 介紹 在數學上,費波那契數列是以遞迴的方法來定義 0 f 0 1 f 1 f f f f f n 2 用文字來說,就是費波那契數列由0和1開始,之後的費波那契係數就是由之前的兩數相加而得出。首幾個費波那契係數是 0,1,1,2,3,5,8,13,21,34,55,89,144,233 oeis中...
斐波那契數列(Fibonacci)
斐波那契數列 無窮數列 1,1,2,3,5,8,13,21,34,55.稱為fibonacci數列。它可以定規地定義為 n 0,1 f n 1 n 1 f n f n 1 f n 2 這是乙個遞迴的關係式,它說明當n大於1時,這個數列的第n項的值,是它前面兩項的和,它用兩個較小的自變數的函式值來定義...