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

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

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

6.? 非尾遞歸的實(shí)用化方案

如之前所說密似,斐波那契數(shù)列的典型遞歸解法時(shí)間復(fù)雜度為O(1.618 ^ n)吗垮,耗時(shí)指數(shù)式快速上升,沒有實(shí)用價(jià)值

仔細(xì)看遞歸調(diào)用過程會(huì)發(fā)現(xiàn)织堂,Calculate_Fibonacci_sequence(n-1) + Calculate_Fibonacci_sequence(n-2)叠艳,這二元遞歸過程會(huì)有很多重復(fù)性中間結(jié)果

那么在遞歸過程中把得到中間結(jié)果用字典保存起來,每當(dāng)一次遞歸調(diào)用都查字典看是否為相同參數(shù)的調(diào)用易阳,如果是就直接返回字典里保存的值

這樣算法時(shí)間復(fù)雜度就降為O(n)附较。通過一個(gè)緩存技巧,讓時(shí)間復(fù)雜度降到可用程度

開始寫出這個(gè)遞歸緩存裝飾器潦俺。Python里裝飾器應(yīng)用非常普遍拒课,在很多情境下方便的模塊化級(jí)聯(lián)

from functools import wraps

def recursive_function_cache(func: function) -> function_value:

? ? '用于緩存遞歸函數(shù)的裝飾器代碼。使用方法:在定義函數(shù)的前一行寫裝飾器“@recursive_function_cache”'

? ? cache = dict()

? ? @wraps(func)

? ? def wrapper(*args, **kwargs):

? ? ? ? parameters = (repr(args), repr(kwargs))

? ? ? ? if parameters not in cache:

? ? ? ? ? ? cache.update({parameters : func(*args, **kwargs)})

? ? ? ? return dict.get(cache, parameters)? #返回緩存的函數(shù)值

? ? return wrapper

讓我們來試一下效果事示,算第100項(xiàng)

>>> print('Fibonacci number= ', Fibonacci_sequence_02(100))

Fibonacci number= 354224848179261915075

原來卡住的情況沒有了早像,秒出結(jié)果

好,再試一下算第1200項(xiàng)

>>> print('Fibonacci number= ', Fibonacci_sequence_02(1200))

RecursionError: maximum recursion depth exceeded while calling a Python object

報(bào)棧溢出錯(cuò)誤

又是一個(gè)對(duì)于實(shí)用化的障礙肖爵。Python默認(rèn)設(shè)置的椔校空間不大,只有1000劝堪。Python官方不建議大家用遞歸冀自,盡量寫成迭代循環(huán)的揉稚。并且官方理念是默認(rèn)設(shè)不大的棧空間凡纳,如果程序有遞歸過深的問題就能在運(yùn)行時(shí)早暴露窃植,早改寫

不過有時(shí)遞歸寫法確實(shí)簡(jiǎn)潔清晰,在對(duì)效率沒有要求時(shí)還是可以用的

那么對(duì)遞歸過程出現(xiàn)溢出錯(cuò)誤荐糜,一個(gè)解決方案就是巷怜,動(dòng)態(tài)增加設(shè)置的限制值

可能會(huì)想到還是用裝飾器這個(gè)很優(yōu)雅的寫法來實(shí)施

然而,當(dāng)考慮還要在遞歸函數(shù)運(yùn)行結(jié)束后恢復(fù)recursionlimit原值

裝飾器就無法單獨(dú)簡(jiǎn)單完成這個(gè)目標(biāo)了(各位可有什么好想法暴氏,歡迎在下方留言探討^_^)

我用函數(shù)參數(shù)傳入方式來實(shí)現(xiàn)這個(gè)解決方案

import sys

def dynamic_increase_recursion_limit(func_str: string) -> eval:

? ? '加載可能溢出的遞歸函數(shù)延塑,動(dòng)態(tài)增加棧空間限制值答渔。使用方法:dynamic_increase_recursion_limit("函數(shù)(參數(shù))")'

? ? Increased_limit = 1000

? ? previous_recursion_limit = sys.getrecursionlimit()

? ? while True:?

? ? ? ? try:

? ? ? ? ? ? result = eval(func_str)

? ? ? ? ? ? sys.setrecursionlimit(previous_recursion_limit)

? ? ? ? ? ? return result

? ? ? ? except RecursionError:

? ? ? ? ? ? sys.setrecursionlimit(sys.getrecursionlimit() + Increased_limit)

來試一下效果

>>> print('Fibonacci number= ', dynamic_regulation_recursion_limit('Fibonacci_sequence_02(1200)'))

Fibonacci

number=?

54877108839480000051413673948383714443800519309123592724494953427039811201064341234954387521525390615504949092187441218246679104731442473022013980160407007017175697317900483275246652938800

運(yùn)行時(shí)間測(cè)時(shí)同前例关带,Total time: 0.012642秒

問題解決

讓沒有實(shí)用價(jià)值的斐波那契數(shù)列遞歸解法變成可用的遞歸解法

未完待續(xù)……

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沼撕,隨后出現(xiàn)的幾起案子宋雏,更是在濱河造成了極大的恐慌,老刑警劉巖务豺,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磨总,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡笼沥,警方通過查閱死者的電腦和手機(jī)蚪燕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奔浅,“玉大人馆纳,你說我怎么就攤上這事⌒阼耄” “怎么了鲁驶?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)舞骆。 經(jīng)常有香客問我灵嫌,道長(zhǎng),這世上最難降的妖魔是什么葛作? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任寿羞,我火速辦了婚禮,結(jié)果婚禮上赂蠢,老公的妹妹穿的比我還像新娘绪穆。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布玖院。 她就那樣靜靜地躺著菠红,像睡著了一般。 火紅的嫁衣襯著肌膚如雪难菌。 梳的紋絲不亂的頭發(fā)上试溯,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音郊酒,去河邊找鬼遇绞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛燎窘,可吹牛的內(nèi)容都是我干的摹闽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼褐健,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼付鹿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蚜迅,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤舵匾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谁不,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纽匙,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年拍谐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馏段。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轩拨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院喜,到底是詐尸還是另有隱情亡蓉,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布喷舀,位于F島的核電站砍濒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏硫麻。R本人自食惡果不足惜爸邢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拿愧。 院中可真熱鬧杠河,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至待诅,卻和暖如春叹坦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卑雁。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工募书, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人序厉。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓锐膜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親弛房。 傳聞我的和親對(duì)象是個(gè)殘疾皇子道盏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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