Fiche récapitulative générée pour impression / export PDF.
Licence 3 · Informatique L3 — Algorithmique, structures de données et graphes
Analyse de la complexité algorithmique
Analyse de la complexité algorithmique
1. Pourquoi mesurer la complexité ?
Pour comparer deux algorithmes résolvant le même problème, on ne mesure pas leur temps d'exécution en secondes (qui dépend de la machine, du langage, etc.) mais le nombre d'opérations élémentaires effectuées, en fonction de la taille de l'entrée. C'est la complexité temporelle. On définit de même la complexité spatiale (mémoire utilisée).
2. Notations de Landau : , ,
Soient . On dit :
- (« est dominée par ») s'il existe et tels que pour tout — majoration asymptotique ;
- s'il existe tels que pour — minoration asymptotique ;
- si et — l'ordre de grandeur exact.
Exemple : . On a (car pour , ) et (car ), donc : l'algorithme est de complexité quadratique.
3. Classes de complexité usuelles
Par ordre croissant de coût (pour grand) : (constant), (logarithmique), (linéaire), (quasi-linéaire), (quadratique), (polynomiale), (exponentielle), (factorielle).
Exemple typique : la recherche dans un tableau trié par dichotomie est ; le tri par insertion est dans le pire cas ; le tri fusion est .
4. Calcul de complexité : boucles et récursivité
Boucles simples : une boucle parcourant éléments une fois coûte . Deux boucles imbriquées, chacune de taille , coûtent (produit des tailles, dans le cas indépendant).
Récursivité — équation de récurrence. Pour un algorithme récursif qui divise le problème en sous-problèmes de taille chacun, avec un coût pour combiner les résultats, la complexité vérifie :
Théorème maître (cas simplifié, ) : en posant :
- si : ;
- si : ;
- si : .
Exemple — tri fusion : sous-tableaux, (taille chacun), fusion en (donc ). On a , donc .
Exemple — recherche dichotomique : sous-problème de taille , coût de combinaison (donc ). , donc .
5. Récursivité naïve : Fibonacci
Le calcul naïf de par double récursion () a une complexité où est le nombre d'or — exponentielle, car l'arbre des appels recalcule de nombreuses fois les mêmes sous-problèmes. La mémoïsation (stocker les résultats déjà calculés) ramène ce coût à : c'est le principe de la programmation dynamique.
6. Pire cas, meilleur cas, cas moyen
On distingue généralement :
- la complexité dans le pire cas : borne valable pour toute entrée de taille (la plus utilisée en pratique, car elle garantit une performance) ;
- la complexité dans le meilleur cas : la plus petite complexité possible parmi les entrées de taille ;
- la complexité en moyenne : espérance sur une distribution donnée des entrées.
Exemple — tri rapide (quicksort) : en moyenne, mais dans le pire cas (pivot systématiquement mal choisi, par exemple sur un tableau déjà trié avec un pivot toujours pris en première position).
7. Récapitulatif
| Notation | Signification |
| majorée asymptotiquement par (à une constante près) | |
| minorée asymptotiquement par | |
| et du même ordre de grandeur | |
| théorème maître : (avec facteur si ) |
Exercices de la leçon
Exercice 1
Que signifie ?
Corrigé
La notation exprime une majoration asymptotique à une constante multiplicative près, valable seulement à partir d'un certain rang (le comportement pour les petites valeurs de n'a pas d'importance).
Exercice 2
Vrai ou faux : un algorithme de complexité est, pour grand, plus rapide qu'un algorithme de complexité .
Corrigé
Vrai. La fonction croît strictement plus lentement que pour assez grand (le rapport ), donc un algorithme devient toujours plus rapide qu'un au-delà d'un certain seuil.
Exercice 3
Quelle est la complexité d'une boucle simple parcourant un tableau de taille une seule fois ?
Corrigé
Une boucle qui exécute une opération constante pour chacun des éléments du tableau coûte : un nombre d'opérations proportionnel à la taille de l'entrée.
Exercice 4
Vrai ou faux : la recherche dichotomique dans un tableau trié de taille a une complexité .
Corrigé
Vrai. À chaque étape, la dichotomie divise par deux la taille de l'espace de recherche, donc le nombre d'étapes nécessaires pour atteindre une taille est .
Exercice 5
Quelle est la complexité, dans le pire cas, du tri rapide (quicksort) ?
Corrigé
Dans le pire cas (pivot systématiquement mal choisi), le tri rapide se dégrade en , bien que sa complexité moyenne soit avec un bon choix de pivot.
Exercice 6
Montrer que est .
Corrigé
Pour : (majoration, ) et (minoration, ). Les deux bornes étant vérifiées, .
Exercice 7
À l'aide du théorème maître avec (cas ), quelle est la complexité du tri fusion ?
Corrigé
, donc on est dans le cas du théorème maître : .
Exercice 8
Pour deux boucles imbriquées, la première parcourant éléments et la seconde (à l'intérieur) parcourant éléments également, quelle est la complexité totale ?
Corrigé
Pour chacune des itérations de la boucle externe, la boucle interne s'exécute fois, donc le nombre total d'opérations est , soit .
Exercice 9
Vrai ou faux : la complexité dans le pire cas est toujours supérieure ou égale à la complexité en moyenne.
Corrigé
Vrai. La complexité en moyenne est une espérance sur toutes les entrées possibles de taille , qui ne peut pas dépasser la valeur maximale (le pire cas) atteinte par cette même quantité.
Exercice 10
Pourquoi le calcul naïf (double récursion sans mémoïsation) de Fibonacci a-t-il une complexité exponentielle, alors que la suite elle-même se calcule en avec une boucle ?
Corrigé
Le problème : redondance des calculs. L'appel récursif génère un arbre d'appels où chaque sous-problème pour est recalculé un grand nombre de fois — par exemple, est appelé à la fois directement (par ) et indirectement (via ). Le nombre total d'appels suit la récurrence , dont la solution est () — une croissance exponentielle.
La solution : éviter la redondance. Une approche itérative (ou récursive avec mémoïsation) calcule chaque valeur une seule fois, en la stockant pour réutilisation ultérieure. En ne gardant en mémoire que les deux derniers termes calculés et en itérant de à , on obtient un algorithme en — chaque valeur intermédiaire est calculée et utilisée immédiatement, sans recalcul.
C'est l'illustration la plus simple du principe de la programmation dynamique : transformer une récursion exponentielle redondante en un calcul polynomial en éliminant les recalculs de sous-problèmes identiques.
Exercice 11
Démontrer, en utilisant le théorème maître, que la recherche dichotomique dans un tableau trié de taille a une complexité .
Corrigé
Mise en équation. À chaque étape de la dichotomie, on compare l'élément cherché à l'élément central du tableau (coût constant ), puis on poursuit la recherche dans une seule des deux moitiés (donc sous-problème), de taille (donc ). La récurrence est :
Application du théorème maître. On identifie avec (coût constant). On calcule .
Comme , on est dans le cas du théorème maître, qui donne .
Conclusion : la recherche dichotomique est . C'est cohérent avec l'intuition : la taille de l'intervalle de recherche est divisée par à chaque étape, donc il faut étapes pour atteindre une taille .
Exercice 12
Un algorithme a la récurrence . Déterminer sa complexité via le théorème maître, et donner un exemple classique d'algorithme suivant cette récurrence.
Corrigé
Identification des paramètres. Dans : sous-problèmes, (chacun de taille ), et avec .
Calcul de . .
Comparaison vs . Comme , on est dans le cas du théorème maître, qui donne :
Exemple classique. Cette récurrence est typique de l'algorithme naïf de multiplication de matrices carrées par blocs récursifs : pour multiplier deux matrices découpées en 4 blocs , la formule par blocs nécessite multiplications récursives de matrices de taille dans la version la plus naïve (et pour les additions de blocs) — donnant en fait , soit (la complexité usuelle, non optimisée, de la multiplication matricielle). Une version simplifiée à sous-appels correspondrait plutôt à un algorithme hypothétique de coût linéaire de combinaison, illustrant ici purement le mécanisme du théorème maître.
Exercice 13
Vrai ou faux : .
Corrigé
Faux. Toute fonction exponentielle croît, à terme, strictement plus vite que n'importe quel polynôme (quel que soit fixé, même très grand comme ) : . C'est un résultat classique d'analyse asymptotique (croissance exponentielle l'emporte toujours sur la croissance polynomiale).
Exercice 14
Démontrer que (formule utile pour analyser la complexité optimale du tri, via la formule de Stirling ).
Corrigé
Formule de Stirling. quand , donc en prenant le logarithme :
Identification du terme dominant. Le terme domine strictement les deux autres ( et ), donc :
Conclusion. Comme et diffèrent d'un facteur multiplicatif constant (), on a aussi . Ce résultat est la base de la preuve que tout algorithme de tri par comparaisons a une complexité dans le pire cas (il y a permutations possibles à distinguer, donc il faut au moins comparaisons pour les départager) — ce qui montre que le tri fusion, avec sa complexité , est optimal parmi les algorithmes de tri par comparaisons.
Exercice 15
On considère l'algorithme récursif de calcul de par exponentiation rapide : si pair, si impair. Établir sa complexité en nombre de multiplications.
Corrigé
Mise en équation. À chaque appel récursif, on réduit le problème de taille à un seul sous-problème de taille (calculer ou ), suivi d'un nombre constant d'opérations supplémentaires (une mise au carré, et éventuellement une multiplication par si est impair). La récurrence est :
Application du théorème maître. , , (coût constant de combinaison). , donc on est dans le cas :
Comparaison avec la méthode naïve. Le calcul naïf de par multiplications successives (, fois) coûte multiplications. L'exponentiation rapide ne nécessite que multiplications — un gain exponentiel en pratique (par exemple, calculer demande environ multiplications au lieu d'un million). Cette technique est à la base de nombreux algorithmes cryptographiques modernes (exponentiation modulaire RSA, etc.).
AlphaMath Académie · Analyse de la complexité algorithmique · Informatique L3 — Algorithmique, structures de données et graphes