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

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

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

在GMP庫(kù)里就有斐波那契數(shù)和數(shù)列的單獨(dú)函數(shù)

11.? GMP內(nèi)置fib函數(shù)解法

這直接引用就可以了

import gmpy2

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

? ? '返回單項(xiàng)的GMP內(nèi)置fib函數(shù)解法'

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

? ? if n>=0:

? ? ? ? return gmpy2.fib(n)

? ? else:

? ? ? ? return None

Fibonacci_sequence_09(1000000)

看一下耗時(shí)多少,同上例

Total time: 0.004522秒

算第100萬(wàn)項(xiàng)Fibonacci數(shù)用時(shí)只有二分遞歸解法的65.6%研叫。果然更快速一些

GMP和Mathematica內(nèi)置算Fibonacci數(shù)的函數(shù)都是用的同一種快速算法

是一種叫二進(jìn)制模冪算法,讓我們來(lái)看看是什么樣

https://gmplib.org/manual/Fibonacci-Numbers-Algorithm.html#Fibonacci-Numbers-Algorithm

引自GMP官網(wǎng)上的資料,用的是這個(gè)遞推式

把n分解為n的二進(jìn)制表示形式灸芳,然后直接迭代遞推益老。遞推迭代是O(log n)孩革,大整數(shù)乘方是O(n*log n)),如前篇里解釋惶翻,那么整個(gè)算法時(shí)間復(fù)雜度也是O(n*(log n))的

那為什么表現(xiàn)的比同樣O(n*(log n))的二分迭代解法更快呢

因?yàn)槎M(jìn)制模冪算法中每步只做兩次大整數(shù)乘法姑蓝,是目前算斐波那契數(shù)大整數(shù)乘法最少的算法鹅心。


12.? 二進(jìn)制模冪解法

好吕粗,不用GMP那C寫Fibonacci數(shù)庫(kù)函數(shù),用Python實(shí)現(xiàn)一遍這個(gè)二進(jìn)制模冪解法(當(dāng)然大數(shù)運(yùn)算還是用到GMP)

我來(lái)寫出來(lái)

import gmpy2

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

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

? ? def Calculate_Fibonacci_sequence (n: int) -> int:

? ? ? ? '返回單項(xiàng)的二進(jìn)制模冪解法'

? ? ? ? if n >= 1 :

? ? ? ? ? ? add_on = (2, -2)? #就是 2*(-1)^k 這項(xiàng)

? ? ? ? ? ? prev_num, current_num = gmpy2.mpz(1), gmpy2.mpz(1)? #設(shè)prev_num為F[1]旭愧,current_num為F[2]

? ? ? ? ? ? for i in range(gmpy2.bit_length(n) - 1, 0, -1):? #從最高位開始遍歷除末位外的每個(gè)二進(jìn)制位

? ? ? ? ? ? ? ? if gmpy2.bit_test(n, i):? #注意bit_test的i參數(shù)0就是第一位(二進(jìn)制表示的最末尾一位)

? ? ? ? ? ? ? ? ? ? prev_num = current_num - prev_num? #prev_num = F[2k] = F[2k+1] - F[2k-1]颅筋,current_num就是等于F[2k+1]

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? current_num = current_num - prev_num? #prev_num就是等于F[2k-1],current_num = F[2k] = F[2k+1] - F[2k-1]

? ? ? ? ? ? ? ? sq_prev_num = prev_num ** 2; sq_current_num = current_num ** 2

? ? ? ? ? ? ? ? prev_num = sq_prev_num + sq_current_num? #F[2k-1] = F[k]^2 + F[k-1]^2

? ? ? ? ? ? ? ? current_num = sq_current_num * 4 - sq_prev_num + add_on[1 if gmpy2.bit_test(n, i) else 0]? #F[2k+1] = 4*F[k]^2 - F[k-1]^2 + 2*(-1)^k

? ? ? ? ? ? if n & 1 == 0:? #迭代完成输枯,再對(duì)末位做個(gè)判斷

? ? ? ? ? ? ? ? current_num = current_num - prev_num

? ? ? ? ? ? return current_num

? ? ? ? elif n == 0:

? ? ? ? ? ? return 0

? ? if n >=0:

? ? ? ? return Calculate_Fibonacci_sequence(n)

? ? else:

? ? ? ? return None

Fibonacci_sequence_10(1000000)

看耗時(shí)多少议泵,同上例

Total time: 0.005285秒

只比純C庫(kù)實(shí)現(xiàn)的慢了不到1ms,Python還是不錯(cuò)的

未完待續(xù)……

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

最后編輯于
?著作權(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ō)我怎么就攤上這事垢箕』ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵条获,是天一觀的道長(zhǎng)茅姜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)月匣,這世上最難降的妖魔是什么钻洒? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮锄开,結(jié)果婚禮上素标,老公的妹妹穿的比我還像新娘。我一直安慰自己萍悴,他們只是感情好头遭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布寓免。 她就那樣靜靜地躺著,像睡著了一般计维。 火紅的嫁衣襯著肌膚如雪袜香。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天鲫惶,我揣著相機(jī)與錄音蜈首,去河邊找鬼。 笑死欠母,一個(gè)胖子當(dāng)著我的面吹牛欢策,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赏淌,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼踩寇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了六水?” 一聲冷哼從身側(cè)響起俺孙,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掷贾,沒(méi)想到半個(gè)月后睛榄,有當(dāng)?shù)厝嗽跇淞掷锇l(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
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朝聋。 院中可真熱鬧嗡午,春花似錦、人聲如沸冀痕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至僻他,卻和暖如春宵距,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吨拗。 一陣腳步聲響...
    開封第一講書人閱讀 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)容