Computational complexity of Fibonacci Sequence

后端 未结 11 1444
慢半拍i
慢半拍i 2020-11-21 10:27

I understand Big-O notation, but I don\'t know how to calculate it for many functions. In particular, I\'ve been trying to figure out the computational complexity of the nai

相关标签:
11条回答
  • 2020-11-21 10:27

    It is simple to calculate by diagramming function calls. Simply add the function calls for each value of n and look at how the number grows.

    The Big O is O(Z^n) where Z is the golden ratio or about 1.62.

    Both the Leonardo numbers and the Fibonacci numbers approach this ratio as we increase n.

    Unlike other Big O questions there is no variability in the input and both the algorithm and implementation of the algorithm are clearly defined.

    There is no need for a bunch of complex math. Simply diagram out the function calls below and fit a function to the numbers.

    Or if you are familiar with the golden ratio you will recognize it as such.

    This answer is more correct than the accepted answer which claims that it will approach f(n) = 2^n. It never will. It will approach f(n) = golden_ratio^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 讨论(0)
  • 2020-11-21 10:29

    There's a very nice discussion of this specific problem over at MIT. On page 5, they make the point that, if you assume that an addition takes one computational unit, the time required to compute Fib(N) is very closely related to the result of Fib(N).

    As a result, you can skip directly to the very close approximation of the Fibonacci series:

    Fib(N) = (1/sqrt(5)) * 1.618^(N+1) (approximately)
    

    and say, therefore, that the worst case performance of the naive algorithm is

    O((1/sqrt(5)) * 1.618^(N+1)) = O(1.618^(N+1))
    

    PS: There is a discussion of the closed form expression of the Nth Fibonacci number over at Wikipedia if you'd like more information.

    0 讨论(0)
  • 2020-11-21 10:31

    It is bounded on the lower end by 2^(n/2) and on the upper end by 2^n (as noted in other comments). And an interesting fact of that recursive implementation is that it has a tight asymptotic bound of Fib(n) itself. These facts can be summarized:

    T(n) = Ω(2^(n/2))  (lower bound)
    T(n) = O(2^n)   (upper bound)
    T(n) = Θ(Fib(n)) (tight bound)
    

    The tight bound can be reduced further using its closed form if you like.

    0 讨论(0)
  • 2020-11-21 10:32

    Recursive algorithm's time complexity can be better estimated by drawing recursion tree, In this case the recurrence relation for drawing recursion tree would be T(n)=T(n-1)+T(n-2)+O(1) note that each step takes O(1) meaning constant time,since it does only one comparison to check value of n in if block.Recursion tree would look like

              n
       (n-1)      (n-2)
    (n-2)(n-3) (n-3)(n-4) ...so on
    

    Here lets say each level of above tree is denoted by i hence,

    i
    0                        n
    1            (n-1)                 (n-2)
    2        (n-2)    (n-3)      (n-3)     (n-4)
    3   (n-3)(n-4) (n-4)(n-5) (n-4)(n-5) (n-5)(n-6)
    

    lets say at particular value of i, the tree ends, that case would be when n-i=1, hence i=n-1, meaning that the height of the tree is n-1. Now lets see how much work is done for each of n layers in tree.Note that each step takes O(1) time as stated in recurrence relation.

    2^0=1                        n
    2^1=2            (n-1)                 (n-2)
    2^2=4        (n-2)    (n-3)      (n-3)     (n-4)
    2^3=8   (n-3)(n-4) (n-4)(n-5) (n-4)(n-5) (n-5)(n-6)    ..so on
    2^i for ith level
    

    since i=n-1 is height of the tree work done at each level will be

    i work
    1 2^1
    2 2^2
    3 2^3..so on
    

    Hence total work done will sum of work done at each level, hence it will be 2^0+2^1+2^2+2^3...+2^(n-1) since i=n-1. By geometric series this sum is 2^n, Hence total time complexity here is O(2^n)

    0 讨论(0)
  • 2020-11-21 10:33

    Just ask yourself how many statements need to execute for F(n) to complete.

    For F(1), the answer is 1 (the first part of the conditional).

    For F(n), the answer is F(n-1) + F(n-2).

    So what function satisfies these rules? Try an (a > 1):

    an == a(n-1) + a(n-2)

    Divide through by a(n-2):

    a2 == a + 1

    Solve for a and you get (1+sqrt(5))/2 = 1.6180339887, otherwise known as the golden ratio.

    So it takes exponential time.

    0 讨论(0)
  • 2020-11-21 10:36

    I agree with pgaur and rickerbh, recursive-fibonacci's complexity is O(2^n).

    I came to the same conclusion by a rather simplistic but I believe still valid reasoning.

    First, it's all about figuring out how many times recursive fibonacci function ( F() from now on ) gets called when calculating the Nth fibonacci number. If it gets called once per number in the sequence 0 to n, then we have O(n), if it gets called n times for each number, then we get O(n*n), or O(n^2), and so on.

    So, when F() is called for a number n, the number of times F() is called for a given number between 0 and n-1 grows as we approach 0.

    As a first impression, it seems to me that if we put it in a visual way, drawing a unit per time F() is called for a given number, wet get a sort of pyramid shape (that is, if we center units horizontally). Something like this:

    n              *
    n-1            **
    n-2           ****  
    ...
    2           ***********
    1       ******************
    0    ***************************
    

    Now, the question is, how fast is the base of this pyramid enlarging as n grows?

    Let's take a real case, for instance F(6)

    F(6)                 *  <-- only once
    F(5)                 *  <-- only once too
    F(4)                 ** 
    F(3)                ****
    F(2)              ********
    F(1)          ****************           <-- 16
    F(0)  ********************************    <-- 32
    

    We see F(0) gets called 32 times, which is 2^5, which for this sample case is 2^(n-1).

    Now, we want to know how many times F(x) gets called at all, and we can see the number of times F(0) is called is only a part of that.

    If we mentally move all the *'s from F(6) to F(2) lines into F(1) line, we see that F(1) and F(0) lines are now equal in length. Which means, total times F() gets called when n=6 is 2x32=64=2^6.

    Now, in terms of complexity:

    O( F(6) ) = O(2^6)
    O( F(n) ) = O(2^n)
    
    0 讨论(0)
提交回复
热议问题