web-dev-qa-db-fra.com

Pourquoi la complexité du calcul de la série de Fibonacci 2 ^ n et non pas n ^ 2?

J'essaie de trouver la complexité de la série de Fibonacci en utilisant un arbre de récurrence et conclu height of tree = O(n) dans le pire des cas, cost of each level = cn, donc complexity = n*n=n^2

Comment se fait-il que O(2^n)?

24
Suri

L'arbre de récurrence pour fib (n) serait quelque chose comme:

                              n       
                           /     \
                          n-1    n-2      --------- maximum 2^1 additions
                         /  \    /   \
                       n-2   n-3 n-3 n-4  -------- maximum 2^2 additions
                      /   \           
                     n-3 n-4              -------- maximum 2^3 additions         
                                                ........
                                          -------- maximum 2^(n-1) additions  
  1. Utilisation de n-1 sur 2 ^ (n-1) car pour fib (5), nous finirons par descendre à fib (1)
  2. Nombre de nœuds internes = Nombre de feuilles - 1 = 2 ^ (n-1) - 1 
  3. Nombre d'additions = Nombre de nœuds internes + Nombre de feuilles = (2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ...) + 2 ^ (n-1)
  4. Nous pouvons remplacer le nombre de nœuds internes par 2 ^ (n-1) - 1 car il sera toujours inférieur à cette valeur: = 2 ^ (n-1) - 1 + 2 ^ (n-1) ~ 2 ^ n
13
Anum Malik

t (n) = t (n-1) + t (n-2) qui peut être résolu par la méthode de l'arbre:

                                  t(n-1)  +  t(n-2)        2^1=2
                                   |         |  
                            t(n-2)+t(n-3)  t(n-3)+t(n-4)   2^2=4  
                                .               .          2^3=8
                                .               .           .
                                .               .           .

de même pour le dernier niveau. . 2 ^ n
cela rendra la complexité temporelle totale => 2 + 4 + 8 + ..... 2 ^ n après avoir résolu le problème ci-dessus, nous aurons la complexité temporelle sous la forme O (2 ^ n) 

6
mukesh

Regarde ca comme ca. Supposons que la complexité du calcul de F(k), le nombre kth de Fibonacci par récursion soit au plus 2^k pour k <= n. Ceci est notre hypothèse d'induction. Alors la complexité de calculer F(n + 1) par récursion est 

F(n + 1) = F(n) + F(n - 1)

qui a la complexité 2^n + 2^(n - 1). Notez que

2^n + 2^(n - 1) = 2 * 2^n / 2 + 2^n / 2 = 3 * 2^n / 2 <= 2 * 2^n = 2^(n + 1).

Nous avons montré par récurrence que l'affirmation selon laquelle le calcul de F(k) par récursion est au plus 2^k est correct.

6
jason

La complexité de la série récursive de Fibonacci est de 2 ^ n:
Ce seront les relations de récurrence pour Fibonacci récursif 

 T(n)=T(n-1)+T(n-2)                  No  of elements  2

Maintenant, résolvons cette relation en utilisant la méthode de substitution (substituant la valeur de T(n-1) et T (n-2))

T(n)=T(n-2)+2*T(n-3)+T(n-4)          No  of elements  4=2^2

Encore une fois en substituant les valeurs du terme ci-dessus, nous aurons

T(n)=T(n-3)+3*T(n-4)+3*T(n-5)+T(n-6)  No  of elements  8=2^3

Après le résoudre complètement, nous obtenons

T(n)={T(n-k)+---------+---------}----------------------------->2^k  eq(3) 

Cela implique que le nombre maximal d'appels récursifs, quel que soit le niveau, sera au maximum de 2 ^ n.
Et pour tous les appels récursifs dans l’équation 3, c’est (1), donc la complexité temporelle sera 2^n* ϴ(1)=2^n 

1
Mohit Yadav

La complexité de la série de Fibonacci est O (F (k)), où F(k) est le kième nombre de Fibonacci. Cela peut être prouvé par induction. C'est trivial pour un cas basé. Et supposons que pour tout k <= n, la complexité du calcul F(k) est c * F (k) + 0 (F (k)), puis pour k = n + 1, la complexité du calcul F (n + 1) est c * F (n) + o(F(n)) + c * F (n-1) + o(F(n-1)) = c * (F (n) + F(n-1)) + o(F(n)) + o(F(n-1)) = O (F (n + 1)). 

1
Zhongyuan

La complexité O (2 ^ n) du calcul du nombre de Fibonacci s'applique uniquement à l'approche de récursivité. Avec quelques espaces supplémentaires, vous pouvez obtenir de bien meilleures performances avec O (n).

public static int fibonacci(int n) throws Exception {

  if (n < 0)
    throws new Exception("Can't be a negative integer")

  if (n <= 1)
    return n;

  int s = 0, s1 = 0, s2 = 1;
  for(int i= 2; i<=n; i++) {
    s = s1 + s2;
    s1 = s2;
    s2 = s;            
  }
  return s;
}
0
vic

Je ne peux pas résister à la tentation de connecter un algorithme linéaire itératif pour Fib au temps exponentiel récursif: si on lit le merveilleux petit livre de Jon Bentley sur "Writing Efficient Algorithms", je crois que c'est un cas simple de "cache": chaque fois que Fib ( k) est calculé, stockez-le dans le tableau FibCached [k]. Chaque fois que Fib (j) est appelé, commencez par vérifier s'il est mis en cache dans FibCached [j]; si oui, retourne la valeur; sinon, utilisez la récursivité. (Regardez l'arbre des appels maintenant ...)

0
Alex B.