簡體   English   中英

斐波那契的Big-O帶有記憶嗎?

[英]Big-O of Fibonacci with memoization?

當我運行該程序時,它看起來像是O(1),因為它幾乎是用於無記名的fib的大量數字。 如果它正在計算先前的數字,那么它要做的就是加法,其結果將是O(1)?

memo = {}
def Fib(n):
    if (n < 2):
        return 1
    if not n in memo:
        memo[n] = Fib(n-1) + Fib(n-2)
    return memo[n]

與沒有備忘錄的斐波那契程序相比,我還給它計時,這是從1到40的繪圖結果: 在此處輸入圖片說明

首先,算法的下限是O(n)僅僅是因為對於給定的n您要用n值填充字典(假設我們正在處理對Fib第一次調用)。

另一方面,對於每個n您在Fib函數中執行的每個操作均攤銷O(1) 因此,總的來說,您第一次致電 Fib將攤銷O(n)

請注意,對於較大的n此值可能會高於O(n)因為not in運行時不是O(1) (僅攤銷O(1) )。 n必須是多少? 不知道,取決於底層的哈希函數。 另外,在達到n之前,您可能會耗盡內存。

現在,這顯然是以空間(即內存)為代價的,它也變為O(n) 而且這僅是在每個整數都占用相同數量的空間的前提下進行的,不幸的是,對於Python而言,這是不正確的。 “不限制整數”方法的結果是,大整數作為數字數組保留在內存中。 由於數字n最多具有log_b(n)+1數字(其中b是數字系統,例如10為十進制系統,因此我不確定哪個Python內部使用),我們得出實際空間復雜度在O(n)之間和O(log_b(n!))

如果我們不在乎是不是第一次打電話,事情就會變得更加復雜。 但是只有一點。 您通常可以輕松地檢查出FibO(max(nk, 1))復雜度,其中k是調用時memo字典的大小。

將其與例如迭代方法進行比較。 在這種方法中,您始終要保留2個最后一個元素和一個計數器。 這樣,您將獲得O(n)時間復雜度和O(1)空間復雜度。

當然,對於朴素的遞歸斐波那契,時間復雜度為O(2^n) ,空間復雜度為O(n) (由於調用堆棧)。

我的感覺是它仍然是O(n),假設您計算Fin(100),則需要在計算100前計算所有數字。確定是否已完成前一次運行,那么您會將其存儲在內存中,但是對於您可以想象並已執行上一個執行的任何數字,我可以想象一個更大的數字:)

也許您可以說它是O(1)攤銷的(與Java中的ArrayList獲得元素的O(1)一樣……實際上是O(n),因為您可能需要調整數組的大小,但是通常情況並非如此,因此O(1)是“可接受的”量度)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM