web-dev-qa-db-fra.com

Détermination de la complexité des fonctions récursives (notation Big O)

J'ai un cours d'informatique à mi-parcours demain et j'ai besoin d'aide pour déterminer la complexité de ces fonctions récursives. Je sais comment résoudre des cas simples, mais j'essaie toujours d'apprendre à résoudre ces cas plus difficiles. Ce ne sont là que quelques exemples de problèmes que je n'ai pas pu résoudre. Toute aide serait très appréciée et aiderait grandement dans mes études, merci!

int recursiveFun1(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun1(n-1);
}

int recursiveFun2(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun2(n-5);
}

int recursiveFun3(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun3(n/5);
}

void recursiveFun4(int n, int m, int o)
{
    if (n <= 0)
    {
        printf("%d, %d\n",m, o);
    }
    else
    {
        recursiveFun4(n-1, m+1, o);
        recursiveFun4(n-1, m, o+1);
    }
}

int recursiveFun5(int n)
{
    for (i = 0; i < n; i += 2) {
        // do something
    }

    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun5(n-5);
}
224
Michael_19

La complexité temporelle, en notation Big O, pour chaque fonction, est dans l’ordre numérique:

  1. La première fonction est appelée récursivement n fois avant d'atteindre le cas de base, de sorte que sa O(n), souvent appelée linéaire.
  2. La deuxième fonction est appelée n-5 à chaque fois; nous en déduisons donc cinq avant de l'appel de la fonction, mais n-5 correspond également à O(n). (En réalité appelé ordre de n/5 fois. Et, O(n/5) = O(n)).
  3. Cette fonction est log (n) base 5, car chaque fois que nous divisons par 5 avant d'appeler la fonction, sa fonction O(log(n)) (base 5), souvent appelée logarithmique et le plus souvent, la notation Big O et l'analyse de complexité utilisent des bases 2.
  4. Dans le quatrième, il s'agit de O(2^n), ou exponentiel, car chaque appel de fonction s'appelle deux fois sauf s'il a été récursif n fois.
  5. En ce qui concerne la dernière fonction, la boucle for prend n/2 puisque nous augmentons de 2, et la récursivité prend n-5 et puisque la boucle for est appelée de manière récursive, la complexité temporelle est donc en (n-5) * (n/2) = (2n-10) * n = 2n ^ 2- 10n, en raison du comportement asymptotique et des considérations de scénario défavorable ou de la limite supérieure à laquelle aspire grand O, nous ne sommes intéressés que par le terme le plus important, donc O(n^2).

    Bonne chance sur vos midterms;)

283
coder

Pour le cas où n <= 0, T(n) = O(1). Par conséquent, la complexité temporelle dépendra du moment où n >= 0.

Nous allons considérer le cas n >= 0 dans la partie ci-dessous.

1.

T(n) = a + T(n - 1)

où a est une constante.

Par induction:

T(n) = n * a + T(0) = n * a + b = O(n)

où a, b sont des constantes.

2.

T(n) = a + T(n - 5)

où a est une constante

Par induction:

T(n) = ceil(n / 5) * a + T(k) = ceil(n / 5) * a + b = O(n)

où a, b sont des constantes et k <= 0

3.

T(n) = a + T(n / 5)

où a est une constante

Par induction:

T(n) = a * log5(n) + T(0) = a * log5(n) + b = O(log n)

où a, b sont une constante

4.

T(n) = a + 2 * T(n - 1)

où a est une constante

Par induction:

T(n) = a + 2a + 4a + ... + 2^n * a + T(0) * 2 ^ n 
     = a * 2^(n+1) - a + b * 2 ^ n
     = (2 * a + b) * 2 ^ n - a
     = O(2 ^ n)

où a, b sont des constantes.

5.

T(n) = n / 2 + T(n - 5)

On peut prouver par induction que T(5k) >= T(5k - d) où d = 0, 1, 2, 3, 4

Ecrire n = 5m - b (m, b sont des entiers; b = 0, 1, 2, 3, 4), puis m = (n + b) / 5:

T(n) = T(5m - b) <= T(5m)

(En fait, pour être plus rigoureux ici, une nouvelle fonction T'(n) devrait être définie telle que T'(5r - q) = T(5r)q = 0, 1, 2, 3, 4. Nous savons que T(n) <= T'(n) a été prouvé ci-dessus. Lorsque nous savons que T'(n) est dans O(f), ce qui signifie qu'il existe une constante b, pour que T'(n) <= a * f(n) + b, nous puissions déduire que T(n) <= a * f(n) + b et par conséquent T(n) est dans O(f). Cette étape n’est pas vraiment nécessaire, mais il est plus facile de penser lorsque vous n’a pas à vous occuper du reste.)

Expansion de T(5m):

T(5m) = 5m / 2 + T(5m - 5) 
      = (5m / 2 + 5 / 2) * m / 2 + T(0) 
      = O(m ^ 2) = O(n ^ 2)

Par conséquent, T(n) est O(n ^ 2).

116
nhahtdh

L’un des meilleurs moyens de déterminer la complexité de l’algorithme récursif consiste à dessiner l’arbre de récursion. Une fois que vous avez l'arbre récursif:

Complexity = length of tree from root node to leaf node * number of leaf nodes
  1. La première fonction aura une longueur de n et le nombre de nœuds feuille 1 de sorte que la complexité sera n*1 = n
  2. La seconde fonction aura la longueur de n/5 et le nombre de nœuds feuille encore 1 de sorte que la complexité sera n/5 * 1 = n/5. Il devrait être approché à n

  3. Pour la troisième fonction, puisque n est divisé par 5 à chaque appel récursif, la longueur de l’arborescence récursive sera log(n)(base 5), et le nombre de nœuds feuilles à nouveau 1, de sorte que la complexité sera log(n)(base 5) * 1 = log(n)(base 5).

  4. Pour la quatrième fonction puisque chaque nœud aura deux nœuds enfants, le nombre de nœuds feuilles sera égal à (2^n) et la longueur de l'arborescence récursive sera n et la complexité sera donc (2^n) * n. Mais comme n est insignifiant devant (2^n), il peut être ignoré et la complexité ne peut être qualifiée que de (2^n).

  5. Pour la cinquième fonction, deux éléments introduisent la complexité. Complexité introduite par la nature récursive de la fonction et complexité introduite par la boucle for dans chaque fonction. En effectuant le calcul ci-dessus, la complexité introduite par la nature récursive de la fonction sera ~ n et la complexité due à la boucle for n. La complexité totale sera n*n.

Remarque: Il s’agit d’un moyen rapide et peu fiable de calculer la complexité (rien d’officiel!). J'adorerais entendre vos commentaires à ce sujet. Merci.

18
Shubham