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);
}
La complexité temporelle, en notation Big O, pour chaque fonction, est dans l’ordre numérique:
O(n)
, souvent appelée linéaire.O(n)
. (En réalité appelé ordre de n/5 fois. Et, O(n/5) = O(n)).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.O(2^n)
, ou exponentiel, car chaque appel de fonction s'appelle deux fois sauf s'il a été récursif n fois.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;)
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)
où 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)
.
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
n
et le nombre de nœuds feuille 1
de sorte que la complexité sera n*1 = n
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
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)
.
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)
.
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.