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

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

之前那幾種算法時(shí)間復(fù)雜度最好的也只是O(n)

下面是幾種高效解法,時(shí)間復(fù)雜度都是O(log n)

7.? 二分遞歸解法

設(shè)n∈R,則有:

F[n]=F[n/2+1]2?F[n/2?1]2=(2F[n/2?1]+F[n/2])F[n/2]????? 當(dāng)n為偶數(shù)時(shí)

F[n]=F[n/2]2+F[n/2+1]2????????????????????????? ? ? ? ?? ???????????????? 當(dāng)n為奇數(shù)時(shí)

下面用遞歸寫出解法然磷,真是很簡單

因?yàn)檫@是二元遞歸函數(shù)捆憎,所以加上上篇的緩存遞歸函數(shù)裝飾器和動(dòng)態(tài)增加椫伲空間函數(shù)

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

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

??? @recursive_function_cache

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

? ? ? ? '返回單項(xiàng)的二分遞歸解法'

? ? ? ? if n >= 2:

??????????? one_half_n = n >> 1

? ? ? ? ? ? if n & 1 == 0:? #當(dāng)n為偶數(shù)項(xiàng)

? ? ? ? ? ? ? ? one_half_fib_n = Calculate_Fibonacci_sequence(one_half_n)

? ? ? ? ? ? ? ? one_half_fib_n_minus_one = Calculate_Fibonacci_sequence(one_half_n - 1)

? ? ? ? ? ? ? ? return (one_half_fib_n_minus_one * 2 + one_half_fib_n) * one_half_fib_n

? ? ? ? ? ? else:? #當(dāng)n為奇數(shù)項(xiàng)

? ? ? ? ? ? ? ? return Calculate_Fibonacci_sequence(one_half_n) ** 2 + Calculate_Fibonacci_sequence(one_half_n + 1) ** 2

? ? ? ? elif n == 1:

? ? ? ? ? ? return 1

? ? ? ? elif n == 0:

? ? ? ? ? ? return 0

? ? if n>=0:

? ? ? ? return Calculate_Fibonacci_sequence(n)

? ? else:

? ? ? ? return None

dynamic_increase_recursion_limit('Fibonacci_sequence_07(1000000)')

用算到第100萬項(xiàng)Fibonacci數(shù)來測量下用時(shí)

Total time: 0.076837秒

算第100萬項(xiàng)只用時(shí)這么點(diǎn)边坤,按前面最快的for迭代解法速度這點(diǎn)時(shí)間也只能算到3萬多〕迹看起來是高效多了

具體的時(shí)間復(fù)雜度是怎樣的呢

這二分法的遞歸形式分析起來有點(diǎn)麻煩

那下面我寫成迭代形式再分析時(shí)間復(fù)雜度吧


8.? 二分迭代解法

用迭代形式實(shí)現(xiàn)這二分解法,看看用時(shí)如何

程序如下:

from collections import deque

def Fibonacci_sequence_08 (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)的二分迭代解法'

? ? ? ? Even = True

? ? ? ? Odd = False

? ? ? ? if n >= 2:

? ? ? ? ? ? fib_n_tree = [n, []]? #數(shù)據(jù)存放格式是列表里前后兩項(xiàng)伙窃,前項(xiàng)是n呻右,后項(xiàng)是對應(yīng)第n項(xiàng)Fibonacci數(shù)或是包含兩個(gè)子節(jié)點(diǎn)的一個(gè)列表

? ? ? ? ? ? fib_n_tier_node_queue = deque()

? ? ? ? ? ? fib_n_cache = dict()

? ? ? ? ? ? fib_merge_stack = []

? ? ? ? ? ? def generating_fib_n_tree(n):

? ? ? ? ? ? ? ? nonlocal fib_n_tier_node_queue, fib_n_cache, current_root

? ? ? ? ? ? ? ? if n >= 2:

? ? ? ? ? ? ? ? ? ? if n in fib_n_cache:

? ? ? ? ? ? ? ? ? ? ? ? child_nodes = dict.get(fib_n_cache, n)

? ? ? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? ? ? child_nodes = [n, []]

? ? ? ? ? ? ? ? ? ? ? ? fib_n_tier_node_queue.append(child_nodes)

? ? ? ? ? ? ? ? ? ? ? ? fib_n_cache.update({n: child_nodes})

? ? ? ? ? ? ? ? elif n == 1:

? ? ? ? ? ? ? ? ? ? child_nodes = (n, 1)

? ? ? ? ? ? ? ? elif n == 0:

? ? ? ? ? ? ? ? ? ? child_nodes = (n, 0)

? ? ? ? ? ? ? ? current_root[1].append(child_nodes)? #將產(chǎn)生的子節(jié)點(diǎn)往current_root里裝子節(jié)點(diǎn)的列表里壓入

? ? ? ? ? ? fib_n_tier_node_queue.append(fib_n_tree)

? ? ? ? ? ? while len(fib_n_tier_node_queue) > 0:? #先從上至下建立二分樹

? ? ? ? ? ? ? ? current_root = fib_n_tier_node_queue.popleft()

? ? ? ? ? ? ? ? n_of_current_root = current_root[0]

? ? ? ? ? ? ? ? one_half_n = n_of_current_root >> 1

? ? ? ? ? ? ? ? if n_of_current_root & 1 == 0:? #當(dāng)n_of_current_root為偶數(shù)項(xiàng)

? ? ? ? ? ? ? ? ? ? generating_fib_n_tree(one_half_n)? #往fib_n_tree里先存兩者中較大的數(shù)字

? ? ? ? ? ? ? ? ? ? generating_fib_n_tree(one_half_n - 1)

? ? ? ? ? ? ? ? ? ? fib_merge_stack.append((current_root, Even))

? ? ? ? ? ? ? ? else:? #當(dāng)n_of_current_root為奇數(shù)項(xiàng)

? ? ? ? ? ? ? ? ? ? generating_fib_n_tree(one_half_n + 1)? #往fib_n_tree里先存兩者中較大的數(shù)字

? ? ? ? ? ? ? ? ? ? generating_fib_n_tree(one_half_n)

? ? ? ? ? ? ? ? ? ? fib_merge_stack.append((current_root, Odd))

? ? ? ? ? ? while len(fib_merge_stack) > 0:? #再二分樹從下至上歸并算出結(jié)果

? ? ? ? ? ? ? ? current_task = fib_merge_stack.pop()

? ? ? ? ? ? ? ? current_root = current_task[0]

? ? ? ? ? ? ? ? odevity = current_task[1]

? ? ? ? ? ? ? ? list_of_current_child_node = current_root[1]

? ? ? ? ? ? ? ? large_value_of_current_child_node = list_of_current_child_node[0][1]

? ? ? ? ? ? ? ? small_value_of_current_child_node = list_of_current_child_node[1][1]

? ? ? ? ? ? ? ? if odevity:

? ? ? ? ? ? ? ? ? results = (small_value_of_current_child_node * 2 +

large_value_of_current_child_node) * large_value_of_current_child_node

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? results = small_value_of_current_child_node ** 2 + large_value_of_current_child_node ** 2

? ? ? ? ? ? ? ??current_root[1] = results

? ? ? ? ? ? return fib_n_tree[1]

? ? ? ? elif n == 1:

? ? ? ? ? ? return 1

? ? ? ? elif n == 0:

? ? ? ? ? ? return 0

? ? if n >= 0:

? ? ? ? return Calculate_Fibonacci_sequence(n)

? ? else:

? ? ? ? return None

Fibonacci_sequence_08(1000000)

還是算第100萬位亡问,Total time: 0.076679秒

用時(shí)幾乎一樣肛宋!用時(shí)縮短了158us只能算計(jì)時(shí)誤差范疇

現(xiàn)在來分析下這個(gè)解法的時(shí)間復(fù)雜度

主干就是建立二叉樹的迭代沉帮,對n不斷二分,搜索新子節(jié)點(diǎn)其屏,迭代次數(shù)是2*log2(n)熄云,時(shí)間復(fù)雜度就是O(log n)

未完待續(xù)……

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市势木,隨后出現(xiàn)的幾起案子板驳,更是在濱河造成了極大的恐慌,老刑警劉巖碍拆,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件若治,死亡現(xiàn)場離奇詭異,居然都是意外死亡感混,警方通過查閱死者的電腦和手機(jī)端幼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弧满,“玉大人婆跑,你說我怎么就攤上這事∑谆啵” “怎么了洽蛀?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疟赊。 經(jīng)常有香客問我郊供,道長,這世上最難降的妖魔是什么近哟? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任驮审,我火速辦了婚禮,結(jié)果婚禮上吉执,老公的妹妹穿的比我還像新娘疯淫。我一直安慰自己,他們只是感情好戳玫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布熙掺。 她就那樣靜靜地躺著,像睡著了一般咕宿。 火紅的嫁衣襯著肌膚如雪币绩。 梳的紋絲不亂的頭發(fā)上蜡秽,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音缆镣,去河邊找鬼芽突。 笑死,一個(gè)胖子當(dāng)著我的面吹牛董瞻,可吹牛的內(nèi)容都是我干的寞蚌。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼钠糊,長吁一口氣:“原來是場噩夢啊……” “哼挟秤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起眠蚂,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤煞聪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逝慧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啄糙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年笛臣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隧饼。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沈堡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出燕雁,到底是詐尸還是另有隱情诞丽,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布拐格,位于F島的核電站僧免,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捏浊。R本人自食惡果不足惜懂衩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望金踪。 院中可真熱鬧浊洞,春花似錦、人聲如沸胡岔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽靶瘸。三九已至苫亦,卻和暖如春尖淘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背著觉。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工村生, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饼丘。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓趁桃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肄鸽。 傳聞我的和親對象是個(gè)殘疾皇子卫病,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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