Fibonacci數(shù)列高效解法大全及時(shí)間復(fù)雜度分析 連載【5】

在數(shù)學(xué)上刃唐,斐波那契數(shù)列是以遞歸的方法來(lái)定義

……續(xù)上回Fibonacci數(shù)列高效解法大全及時(shí)間復(fù)雜度分析 連載【4】

來(lái)看profile的記錄分析,看時(shí)間具體用在哪個(gè)部分了

一看前方,絕大部分時(shí)間耗在兩句results上了

看來(lái)主要都用來(lái)大整數(shù)運(yùn)算了

下面來(lái)試一下

把這程序里兩句“results = ”后面的大數(shù)運(yùn)算注釋掉,換成1。也就是兩句都成“results = 1”

再運(yùn)行計(jì)時(shí)看看

Total time: 0.000753秒

很驚人原在,去掉大數(shù)運(yùn)算后饭宾,運(yùn)行時(shí)間縮短成了原用時(shí)的1%。也就是99%時(shí)間消耗在Python內(nèi)置的大數(shù)運(yùn)算上了

下面試下用號(hào)稱地球上最好的大數(shù)運(yùn)算庫(kù)替換掉Python內(nèi)置的大數(shù)運(yùn)算


9.? 應(yīng)用GMP庫(kù)

全稱是GNU Multiple Precision Arithmetic Library凶异,即GNU高精度算術(shù)運(yùn)算庫(kù)蜀撑,這是一個(gè)C寫成的高效大數(shù)運(yùn)算庫(kù)

gmpy2是Python下對(duì)GMP庫(kù)的封裝

安裝很簡(jiǎn)單,在操作系統(tǒng)下打命令pip install gmpy2剩彬,就安裝好了

應(yīng)用到程序也很簡(jiǎn)單

把上面的二分迭代解法程序開(kāi)頭添加一行

from gmpy2 import mpz

再把程序里

child_nodes = (n, 1)

child_nodes = (n, 0)

改成

child_nodes = (n, mpz(1))

child_nodes = (n, mpz(0))

就可以了

運(yùn)行看一下用時(shí)

Total time: 0.00689297秒

是原用Python內(nèi)置大數(shù)運(yùn)算用時(shí)的9%

效果顯著酷麦。可見(jiàn)Python內(nèi)置大數(shù)運(yùn)算效率確實(shí)不怎么樣

相關(guān)大整數(shù)乘法高效算法的介紹可參見(jiàn)這篇《【算法】大數(shù)乘法問(wèn)題及其高效算法

極大整數(shù)乘法的時(shí)間復(fù)雜度為O(n*log n)喉恋,簡(jiǎn)記為mul(n)

前面二分解法本身時(shí)間復(fù)雜度是O(log n)

現(xiàn)在把大數(shù)因素考慮進(jìn)去沃饶。大數(shù)時(shí)間復(fù)雜度的n可以用二進(jìn)制位數(shù)表示

第n項(xiàng)斐波那契數(shù)的二進(jìn)制位數(shù)k跟n是線性關(guān)系,n*10瀑晒,那位數(shù)k也是*10

二分解法時(shí)間復(fù)雜度是O(log n)绍坝,也就是迭代log2(n)輪

現(xiàn)在把極大整數(shù)乘法時(shí)間復(fù)雜度代入

每輪參與乘法的數(shù)字二進(jìn)制位數(shù)大致為2^i,也就是mul(2^i)

也就是在大數(shù)情況下二分解法的總體時(shí)間復(fù)雜度為O(n*(log n))

注:看這篇《為什么算法漸進(jìn)復(fù)雜度中對(duì)數(shù)的底數(shù)總為2


10.? 矩陣解法

斐波那契數(shù)列和矩陣的關(guān)系推導(dǎo)我看到GoCalf Blog里寫的一段非常清晰苔悦,特在此引用

http://www.gocalf.com/blog/calc-fibonacci.html

這解法就是求矩陣的n-1次冪轩褐。矩陣冪運(yùn)算也能根據(jù)下面公式迭代二分加速

就是所謂的矩陣快速冪

Python里庫(kù)很豐富,大名鼎鼎的numpy就是一個(gè)有關(guān)矩陣的庫(kù)玖详。這庫(kù)是有優(yōu)化的把介,算矩陣冪就不用個(gè)人再寫什么矩陣快速冪函數(shù)了

用numpy庫(kù)就能很簡(jiǎn)單的寫出來(lái)

因?yàn)閚umpy沒(méi)有大數(shù)支持,大數(shù)運(yùn)算還是要用GMP庫(kù)

import numpy.matlib

from gmpy2 import mpz

def Fibonacci_sequence_06 (n: int) -> int:? #參數(shù)n是表示求第n項(xiàng)Fibonacci數(shù)

? ? '返回單項(xiàng)的矩陣解法'

? ? assert isinstance(n, int), 'n is an error of non-integer type.'

? ? if n>=0:

? ? ? ? fib_matrix = numpy.mat(((mpz(1), mpz(1)), (mpz(1), mpz(0))))

? ? ? ? fib_matrix **= n-1

? ? ? ? return fib_matrix[0,0]

? ? else:

? ? ? ? return None

Fibonacci_sequence_06(1000000)

同上測(cè)用時(shí)

Total time: 0.042466秒

這冪運(yùn)算是二分加速的蟋座,時(shí)間復(fù)雜度為O(log n)

對(duì)于固定階矩陣相乘拗踢,乘的次數(shù)是個(gè)常數(shù),也就是O(1)向臀。雖然這個(gè)常數(shù)比較大^_*

代入大數(shù)時(shí)間復(fù)雜度巢墅,總體復(fù)雜度也是O(n*(log n))

這兒來(lái)解釋下為何矩陣快速冪比二分遞歸解法時(shí)間常數(shù)大

我們?cè)賮?lái)仔細(xì)看看斐波那契數(shù)列的矩陣形式:


會(huì)發(fā)現(xiàn) z 和 y 必然相等,z 沒(méi)必要再計(jì)算一遍券膀。

t = x - y君纫,因此 t 也沒(méi)必要再計(jì)算一遍。

只需要計(jì)算矩陣第一列的那兩個(gè)元素即可:


矩陣快速冪中兩個(gè)矩陣相乘實(shí)際可分解為8次兩個(gè)大整數(shù)乘法芹彬,而二分遞歸中只需要3次兩個(gè)大整數(shù)乘法蓄髓。所以二分遞歸時(shí)間常數(shù)小。

這兒提一下通項(xiàng)公式解法

Fibonacci數(shù)列通項(xiàng)公式

其實(shí)與矩陣快速冪是等價(jià)的舒帮,見(jiàn)《幾種計(jì)算Fibonacci數(shù)列算法的時(shí)間復(fù)雜度分析

未完待續(xù)……

Fibonacci數(shù)列高效解法大全及時(shí)間復(fù)雜度分析 連載【6】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末会喝,一起剝皮案震驚了整個(gè)濱河市陡叠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肢执,老刑警劉巖枉阵,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蔚万,居然都是意外死亡岭妖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門反璃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人假夺,你說(shuō)我怎么就攤上這事淮蜈。” “怎么了已卷?”我有些...
    開(kāi)封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵梧田,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我侧蘸,道長(zhǎng)裁眯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任讳癌,我火速辦了婚禮穿稳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晌坤。我一直安慰自己逢艘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布骤菠。 她就那樣靜靜地躺著它改,像睡著了一般。 火紅的嫁衣襯著肌膚如雪商乎。 梳的紋絲不亂的頭發(fā)上央拖,一...
    開(kāi)封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音鹉戚,去河邊找鬼鲜戒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛崩瓤,可吹牛的內(nèi)容都是我干的袍啡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼却桶,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼境输!你這毒婦竟也來(lái)了蔗牡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗅剖,失蹤者是張志新(化名)和其女友劉穎辩越,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體信粮,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黔攒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了强缘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片督惰。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旅掂,靈堂內(nèi)的尸體忽然破棺而出赏胚,到底是詐尸還是另有隱情,我是刑警寧澤商虐,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布觉阅,位于F島的核電站,受9級(jí)特大地震影響秘车,放射性物質(zhì)發(fā)生泄漏典勇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一叮趴、第九天 我趴在偏房一處隱蔽的房頂上張望割笙。 院中可真熱鬧,春花似錦疫向、人聲如沸咳蔚。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谈火。三九已至,卻和暖如春舌涨,著一層夾襖步出監(jiān)牢的瞬間糯耍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工囊嘉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留温技,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓扭粱,卻偏偏與公主長(zhǎng)得像舵鳞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子琢蛤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容