簡體   English   中英

遞歸斐波那契的 Big O 的非數學解釋是什么?

[英]What is a non-mathematical explanation for the Big O of recursive fibonacci?

我閱讀了關於遞歸斐波那契數列的 Big O 的兩篇文章,但仍然沒有概念性地理解為什么它是O(2^n)

這不是此鏈接的副本。 請不要標記為重復。 我正在尋找一個概念性的答案

這是最簡單的遞歸函數之一,我想了解如何看待它並在沒有復雜數學和證明的情況下確定大 O。

// O(2^n)
function fiboR(n){
  if( n === 0 || n === 1 ){
    return n;
  } else if ( n >=2 ){
    return fiboR(n-1) + fiboR(n-2);
  }
}

例如,迭代版本的 Big O 是O(n) 我可以看看,隨着 n 的增加,while 循環迭代線性增加。 不需要復雜的數學或冗長的證明。

// O(n)
function fibo(n){
  let prev0 = 0;
  let prev1 = 1;
  if( n === 0 || n === 1 ){
    return n;
  }
  while( n-- >= 2){
    sum = prev0 + prev1;
    prev0 = prev1;
    prev1 = sum;
  }
  return sum;
}

大量朴素的遞歸函數具有指數級復雜性,因此要牢記這一點。

考慮這個函數:

function fiboR1(n){
  if( n === 0 || n === 1 ){
    return n;
  } else if ( n >=2 ){
    return fiboR1(n-1) + fiboR1(n-1);
  }
}

好的,所以fiboR1實際上並不計算斐波那契數列。 那沒關系。 請注意,它的漸近復雜度至少是fiboR復雜度。 這是因為對fiboR1(n-1)的兩次遞歸調用比對fiboR(n-1)和對fiboR(n-2)一次調用更昂貴。 那么讓我們想想fiboR1的復雜度是fiboR1

讓我們考慮對fiboR1(100)的示例調用。

fiboR1(100) = 2 * fiboR1(99)
            = 4 * fiboR1(98)
            = 8 * fiboR1(97)
            = 16 * fiboR1(96)
            = 32 * fiboR1(95)
            = 64 * fiboR1(94)
            ...

現在看到模式了嗎? 我們對fiboR1進行了O(2^n)遞歸調用,每次調用都是一個恆定時間分支。 所以fiboR1O(2^n) ,這意味着通過擴展, fiboR也是O(2^n) ,因為 big-O 是一個上限函數。

如果你知道斐波那契數列的封閉形式,我們也可以直接為fiboR做這個例子。 讓我們考慮fiboR(100)

fiboR(100) = fiboR(99) + fiboR(98)
           = 2 * fiboR(98) + fiboR(97)
           = 3 * fiboR(97) + 2 * fiboR(96)
           = 5 * fiboR(96) + 3 * fiboR(95)
           = 8 * fiboR(95) + 5 * fiboR(94)
           = 13 * fiboR(94) + 8 * fiboR(93)
           ...

遞歸函數調用的次數遵循斐波那契數列。 斐波那契數列的封閉形式在n呈指數。 事實上,它是O(((1+sqrt{5})/2)^n) ,大約是O(1.6^n)

通過繪制函數調用圖來計算很簡單。 只需為 n 的每個值添加函數調用,然后查看數字如何增長。

大 O 是 O(Z^n),其中 Z 是黃金比例或大約 1.62。

當我們增加 n 時,雷諾數和斐波那契數都接近這個比率。

2 (2 -> 1, 0)

4 (3 -> 2, 1) (2 -> 1, 0)

8 (4 -> 3, 2) (3 -> 2, 1) (2 -> 1, 0)
            (2 -> 1, 0)


14 (5 -> 4, 3) (4 -> 3, 2) (3 -> 2, 1) (2 -> 1, 0)
            (2 -> 1, 0)

            (3 -> 2, 1) (2 -> 1, 0)

22 (6 -> 5, 4)
            (5 -> 4, 3) (4 -> 3, 2) (3 -> 2, 1) (2 -> 1, 0)
                        (2 -> 1, 0)

                        (3 -> 2, 1) (2 -> 1, 0)

            (4 -> 3, 2) (3 -> 2, 1) (2 -> 1, 0)
                        (2 -> 1, 0)

假設您接受該函數是正確的,即它確實計算了斐波那契數,那么很容易證明它的運行時間必須是指數級的:它在基本情況下只返回 0 或 1,並且只產生更大的結果通過將較小的結果相加。

由於斐波那契數以指數方式增長,因此通過將許多 1 相加來制作它們的唯一方法就是以指數方式添加許多 1。 每個結果只會添加到最終總數中一次,因此必須以指數方式多次執行基本情況才能將所有這些 1 生成為不同的結果。

暫無
暫無

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

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