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)
?
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
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)
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.
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
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)).
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;
}
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 ...)