{"id":92,"date":"2025-06-07T14:11:28","date_gmt":"2025-06-07T12:11:28","guid":{"rendered":"https:\/\/boissiebruno-pageperso-pi.ovh\/?p=92"},"modified":"2025-06-07T14:31:20","modified_gmt":"2025-06-07T12:31:20","slug":"complexite-algorithmique-notions-exemples-et-importance","status":"publish","type":"post","link":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/","title":{"rendered":"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction \u2013 Complexit\u00e9 algorithmique vs th\u00e9orie de la complexit\u00e9<\/h2>\n\n\n\n<p>En informatique, l\u2019<strong>analyse de la complexit\u00e9 algorithmique<\/strong> consiste \u00e0 \u00e9tudier le co\u00fbt d\u2019ex\u00e9cution d\u2019un algorithme en fonction de la taille de ses donn\u00e9es d\u2019entr\u00e9e. Elle vise \u00e0 mesurer les ressources n\u00e9cessaires (temps de calcul, m\u00e9moire\u2026) en fonction de <em>n<\/em>, la taille de l\u2019instance. Par exemple, on pourra exprimer que <em>\u00ab&nbsp;cet algorithme n\u00e9cessite un nombre d\u2019op\u00e9rations proportionnel \u00e0 n\u00b2&nbsp;\u00bb<\/em>. L\u2019objectif est de pouvoir comparer l\u2019efficacit\u00e9 d\u2019algorithmes diff\u00e9rents sans d\u00e9pendre d\u2019un langage ou d\u2019une machine en particulier. Cette analyse se focalise souvent sur le <strong>pire cas<\/strong> (input le plus d\u00e9favorable) et le <strong>comportement asymptotique<\/strong> quand <em>n<\/em> devient grand. On utilise pour cela des notations math\u00e9matiques comme le <strong>Grand O<\/strong> (que nous verrons plus loin). Il s\u2019agit donc d\u2019\u00e9valuer rigoureusement <em>\u00ab&nbsp;combien de temps&nbsp;\u00bb<\/em> ou <em>\u00ab&nbsp;combien d\u2019espace m\u00e9moire&nbsp;\u00bb<\/em> un algorithme prendra, en fonction de <em>n<\/em>, lorsque <em>n<\/em> grandit vers l\u2019infini. Cette d\u00e9marche permet de comparer l\u2019efficacit\u00e9 de diff\u00e9rentes approches et de pr\u00e9voir leur passage \u00e0 l\u2019\u00e9chelle.<\/p>\n\n\n\n<p>Il faut distinguer cela de la <strong>th\u00e9orie de la complexit\u00e9 computationnelle<\/strong> (informatique th\u00e9orique). La th\u00e9orie de la complexit\u00e9 ne s\u2019int\u00e9resse plus \u00e0 un algorithme en particulier, mais au probl\u00e8me lui-m\u00eame&nbsp;: <em>quelle est la difficult\u00e9 intrins\u00e8que de ce probl\u00e8me&nbsp;?<\/em> On cherche \u00e0 classifier les <strong>probl\u00e8mes<\/strong> (et non les algorithmes individuels) selon les ressources minimales n\u00e9cessaires pour les r\u00e9soudre. Par exemple, on distingue la classe des probl\u00e8mes r\u00e9solus en temps polynomial (classe <strong>P<\/strong>) de ceux pour lesquels aucun algorithme polynomial n\u2019est connu (classe <strong>NP<\/strong> etc.). Cette th\u00e9orie introduit des classes de complexit\u00e9 et \u00e9tudie leurs relations (fameuse question P vs NP, etc.). <strong>Complexit\u00e9 algorithmique<\/strong> et <strong>complexit\u00e9 computationnelle<\/strong> sont li\u00e9es, mais \u00e0 des \u00e9chelles diff\u00e9rentes&nbsp;: la premi\u00e8re analyse des algorithmes concrets, la seconde classe des probl\u00e8mes abstraits par difficult\u00e9. Dans cet article, nous nous concentrerons sur l\u2019analyse de la complexit\u00e9 des algorithmes et sur les outils pour l\u2019estimer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Complexit\u00e9 en temps et en espace<\/h2>\n\n\n\n<p>Deux des mesures de complexit\u00e9 les plus courantes sont la <strong>complexit\u00e9 en temps<\/strong> et la <strong>complexit\u00e9 en espace<\/strong>. La <strong>complexit\u00e9 en temps<\/strong> d\u2019un algorithme est une fonction qui associe \u00e0 chaque taille d\u2019entr\u00e9e <em>n<\/em> le temps de calcul n\u00e9cessaire (typiquement le nombre d\u2019op\u00e9rations \u00e9l\u00e9mentaires effectu\u00e9es). On exprime ce temps de calcul de mani\u00e8re <em>ind\u00e9pendante<\/em> de la machine utilis\u00e9e, en comptant par exemple les it\u00e9rations, les comparaisons ou toute op\u00e9ration significative. Par convention, on \u00e9value souvent le <strong>temps d\u2019ex\u00e9cution dans le pire cas<\/strong>, c\u2019est-\u00e0-dire le nombre maximal d\u2019\u00e9tapes que l\u2019algorithme effectuera pour une entr\u00e9e de taille <em>n<\/em> donn\u00e9e. (On peut \u00e9galement \u00e9tudier le <strong>meilleur cas<\/strong> ou le <strong>cas moyen<\/strong>, mais le pire cas donne une garantie sup\u00e9rieure sur le comportement de l\u2019algorithme.) Lorsque <em>n<\/em> devient tr\u00e8s grand, on s\u2019int\u00e9resse surtout \u00e0 l\u2019<strong>ordre de grandeur asymptotique<\/strong> du temps d\u2019ex\u00e9cution plut\u00f4t qu\u2019aux constantes multiplicatives&nbsp;; cela permet de comparer l\u2019efficacit\u00e9 de deux algorithmes sur le long terme.<\/p>\n\n\n\n<p>De m\u00eame, la <strong>complexit\u00e9 en espace<\/strong> mesure la quantit\u00e9 de m\u00e9moire utilis\u00e9e par un algorithme en fonction de la taille de l\u2019entr\u00e9e. On \u00e9value typiquement le nombre maximal de cases m\u00e9moire occup\u00e9es simultan\u00e9ment durant l\u2019ex\u00e9cution (en plus de l\u2019entr\u00e9e elle-m\u00eame). Par exemple, un algorithme de tri <em>en place<\/em> qui ne n\u00e9cessite que quelques variables temporaires a une complexit\u00e9 en espace faible (constante), tandis qu\u2019un algorithme qui doit copier ses donn\u00e9es aura une complexit\u00e9 en espace lin\u00e9aire en la taille de celles-ci. Comme pour le temps, on consid\u00e8re souvent le pire cas et le comportement asymptotique. Il est important de noter que temps et espace peuvent \u00eatre en <strong>compromis<\/strong>&nbsp;: certains algorithmes utilisent plus de m\u00e9moire pour gagner du temps, et inversement. Id\u00e9alement, on cherche des solutions \u00e9conomes \u00e0 la fois en temps d\u2019ex\u00e9cution et en utilisation m\u00e9moire.<\/p>\n\n\n\n<p>En r\u00e9sum\u00e9, la complexit\u00e9 en temps nous indique <em>combien de temps de calcul<\/em> demande un algorithme en fonction de <em>n<\/em>, et la complexit\u00e9 en espace indique <em>combien de m\u00e9moire<\/em> il requiert. Ces deux m\u00e9triques aident \u00e0 anticiper si un algorithme sera praticable sur de grandes entr\u00e9es (par exemple, un programme en temps lin\u00e9aire sera faisable sur des millions de donn\u00e9es, tandis qu\u2019un programme en temps exponentiel ne le sera plus au-del\u00e0 de quelques dizaines d\u2019\u00e9l\u00e9ments).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Notations asymptotiques&nbsp;: O, \u03a9, \u0398<\/h2>\n\n\n\n<p>Pour exprimer de fa\u00e7on rigoureuse la complexit\u00e9 en fonction de <em>n<\/em>, on utilise les <strong>notations asymptotiques<\/strong>&nbsp;: principalement <strong>O<\/strong> (\u00ab&nbsp;grand O&nbsp;\u00bb), <strong>\u03a9<\/strong> (om\u00e9ga) et <strong>\u0398<\/strong> (th\u00eata). Celles-ci permettent de donner des bornes sur la croissance d\u2019une fonction lorsque <em>n<\/em> tend vers l\u2019infini, en ignorant les constantes multiplicatives et les termes de plus faible ordre. Intuitivement, on cherche \u00e0 cat\u00e9goriser une fonction de complexit\u00e9 (par exemple <em>T(n)<\/em>) par rapport \u00e0 une fonction de r\u00e9f\u00e9rence plus simple (par exemple <em>n<\/em>, <em>n\u00b2<\/em>, <em>n log n<\/em>, etc.).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Notation O (borne sup\u00e9rieure)<\/strong>\u00a0: On dit que <em>f(n) = O(g(n))<\/em> si <em>f(n)<\/em> cro\u00eet au plus aussi vite qu\u2019une constante fois <em>g(n)<\/em> lorsque <em>n<\/em> est grand. Plus formellement, il existe une constante positive <em>c<\/em> et un rang <em>n\u2080<\/em> tels que pour tout <em>n \u2265 n\u2080<\/em>, on ait <em>f(n) \u2264 c \u00b7 g(n)<\/em>. Cette notation fournit donc une <strong>borne sup\u00e9rieure asymptotique<\/strong> \u2013 elle garantit que, pour <em>n<\/em> suffisamment grand, <em>f(n)<\/em> ne d\u00e9passe pas <em>g(n)<\/em> \u00e0 un facteur constant pr\u00e8s. En complexit\u00e9, <em>O(g(n))<\/em> d\u00e9signe l\u2019ensemble des fonctions qui sont au plus de l\u2019ordre de <em>g(n)<\/em>. Par exemple, si un algorithme effectue au plus <em>3n\u00b2 + 5n + 2<\/em> op\u00e9rations, on dira qu\u2019il est <em>O(n\u00b2)<\/em> (car pour <em>n<\/em> grand, <em>3n\u00b2 + 5n + 2<\/em> est domin\u00e9 par une constante fois <em>n\u00b2<\/em>). La notation O sert surtout \u00e0 exprimer le <strong>pire cas<\/strong> d\u2019un algorithme\u00a0: <em>\u00ab\u00a0cet algorithme est O(n\u00b2)\u00a0\u00bb<\/em> signifie que son temps d\u2019ex\u00e9cution cro\u00eet au plus comme le carr\u00e9 de <em>n<\/em>. <strong>Important<\/strong>\u00a0: dire <em>\u00ab\u00a0f(n) est O(g(n))\u00a0\u00bb<\/em> n\u2019exclut pas que <em>f(n)<\/em> puisse \u00eatre bien plus petit que <em>g(n)<\/em> pour de grandes valeurs de <em>n<\/em> (c\u2019est juste une majoration).<\/li>\n\n\n\n<li><strong>Notation \u03a9 (borne inf\u00e9rieure)<\/strong>\u00a0: De mani\u00e8re duale, on dit que <em>f(n) = \u03a9(g(n))<\/em> si <em>f(n)<\/em> cro\u00eet au moins aussi vite (\u00e0 une constante pr\u00e8s) que <em>g(n)<\/em> lorsque <em>n<\/em> est grand. Formellement, il existe des constantes <em>c\u2019 > 0<\/em> et <em>n\u2080<\/em> telles que pour tout <em>n \u2265 n\u2080<\/em>, <em>f(n) \u2265 c\u2019 \u00b7 g(n)<\/em>. La notation \u03a9 donne une <strong>borne inf\u00e9rieure asymptotique<\/strong> \u2013 elle assure qu\u2019asymptotiquement, <em>f(n)<\/em> ne peut pas cro\u00eetre plus lentement que <em>g(n)<\/em>. En termes de complexit\u00e9, <em>\u03a9(g(n))<\/em> est souvent utilis\u00e9e pour le <strong>meilleur cas<\/strong> d\u2019un algorithme ou pour affirmer qu\u2019un probl\u00e8me n\u00e9cessite au moins un certain co\u00fbt. Par exemple, la recherche s\u00e9quentielle dans une liste non tri\u00e9e est <em>\u03a9(n)<\/em> car il faut au minimum parcourir <em>n<\/em> \u00e9l\u00e9ments dans le pire des cas pour \u00eatre s\u00fbr de trouver une valeur donn\u00e9e (m\u00eame si en moyenne on peut parfois s\u2019arr\u00eater plus t\u00f4t).<\/li>\n\n\n\n<li><strong>Notation \u0398 (borne \u00e9quivalente, croissance \u00ab\u00a0serr\u00e9e\u00a0\u00bb)<\/strong>\u00a0: On dit que <em>f(n) = \u0398(g(n))<\/em> s\u2019il existe deux constantes <em>c\u2081, c\u2082 > 0<\/em> et <em>n\u2080<\/em> tels que <em>c\u2081\u00b7g(n) \u2264 f(n) \u2264 c\u2082\u00b7g(n)<\/em> pour tout <em>n \u2265 n\u2080<\/em>. Autrement dit, <em>f(n)<\/em> est \u00e0 la fois <em>O(g(n))<\/em> et <em>\u03a9(g(n))<\/em>. La notation \u0398 d\u00e9crit une <strong>croissance asymptotique \u00e9quivalente<\/strong>\u00a0: <em>f(n)<\/em> et <em>g(n)<\/em> sont du m\u00eame ordre de grandeur asymptotique. C\u2019est la notion de borne <strong>serr\u00e9e<\/strong>. Par exemple, si l\u2019on a <em>f(n) = 2n\u00b2 + 3n + 1<\/em>, alors <em>f(n) = \u0398(n\u00b2)<\/em> (car cette fonction est born\u00e9e \u00e0 la fois au-dessus et en dessous par une constante fois <em>n\u00b2<\/em> pour <em>n<\/em> grand). En complexit\u00e9 des algorithmes, \u00e9tablir que le temps d\u2019un algorithme est \u0398(g(n)) signifie qu\u2019on a cern\u00e9 pr\u00e9cis\u00e9ment son ordre de croissance dominant. Si de plus un probl\u00e8me admet un algorithme en <em>O(g(n))<\/em> et qu\u2019on peut prouver qu\u2019aucun algorithme ne peut faire mieux que <em>\u03a9(g(n))<\/em>, alors <em>g(n)<\/em> est l\u2019ordre de complexit\u00e9 <strong>optimal<\/strong> du probl\u00e8me.<\/li>\n<\/ul>\n\n\n\n<p>En r\u00e9sum\u00e9, <strong>O<\/strong> donne une borne haute (au-dessus), <strong>\u03a9<\/strong> une borne basse (en dessous), et <strong>\u0398<\/strong> indique que la fonction de co\u00fbt est encadr\u00e9e des deux c\u00f4t\u00e9s par la m\u00eame forme (croissance \u00e9quivalente). Dans la pratique, on utilise le plus souvent le <strong>Grand O<\/strong> pour exprimer le temps de calcul maximal d\u2019un algorithme. Par exemple&nbsp;: <em>\u00ab&nbsp;l\u2019algorithme de tri par insertion est O(n\u00b2) dans le pire cas&nbsp;\u00bb<\/em>. On peut parfois pr\u00e9ciser qu\u2019il est aussi <em>\u03a9(n)<\/em> dans le meilleur cas (donn\u00e9es d\u00e9j\u00e0 tri\u00e9es), etc. Ces notations asymptotiques permettent d\u2019ignorer les constantes multiplicatives et les termes sub-dominants, ce qui donne une vision claire de l\u2019<strong>\u00e9volutivit\u00e9<\/strong> d\u2019un algorithme lorsque la taille des donn\u00e9es augmente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Exemples concrets de complexit\u00e9 (avec code)<\/h2>\n\n\n\n<p>Apr\u00e8s la th\u00e9orie, passons \u00e0 la pratique&nbsp;: examinons quelques <strong>algorithmes classiques<\/strong> et analysons leur complexit\u00e9. Nous pr\u00e9senterons pour chacun un extrait de code en Python et expliquerons comment le nombre d\u2019op\u00e9rations \u00e9volue en fonction de <em>n<\/em>. Ces exemples concrets vont illustrer les notions de complexit\u00e9 lin\u00e9aire, logarithmique, quadratique, cubique, etc., que nous avons \u00e9voqu\u00e9es.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Recherche lin\u00e9aire \u2013 Complexit\u00e9 O(n)<\/h3>\n\n\n\n<p>Commen\u00e7ons par un algorithme simple&nbsp;: la <strong>recherche lin\u00e9aire<\/strong> (ou s\u00e9quentielle) d\u2019une valeur dans un tableau non tri\u00e9. L\u2019id\u00e9e est de parcourir la liste \u00e9l\u00e9ment par \u00e9l\u00e9ment jusqu\u2019\u00e0 trouver l\u2019\u00e9l\u00e9ment cible (ou arriver \u00e0 la fin sans le trouver). Voici une impl\u00e9mentation Python de la recherche lin\u00e9aire&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def recherche_lineaire(tableau, cible):\n    for i, element in enumerate(tableau):\n        if element == cible:\n            return i   # renvoie l'indice o\u00f9 la cible est trouv\u00e9e\n    return -1          # renvoie -1 si la cible n'est pas pr\u00e9sente\n<\/code><\/pre>\n\n\n\n<p>Dans le pire des cas (par exemple, si la valeur recherch\u00e9e est absente du tableau ou se trouve en derni\u00e8re position), cette fonction parcourra toute la liste de longueur <em>n<\/em>. Le nombre de comparaisons sera alors proportionnel \u00e0 <em>n<\/em>. On peut donc dire que la recherche lin\u00e9aire a une <strong>complexit\u00e9 en temps O(n)<\/strong> dans le pire cas. En effet, le temps d\u2019ex\u00e9cution cro\u00eet lin\u00e9airement avec le nombre d\u2019\u00e9l\u00e9ments&nbsp;: si on double la taille de la liste, le temps de recherche maximal double approximativement. \u00c0 l\u2019inverse, le meilleur cas serait que la valeur soit trouv\u00e9e au tout d\u00e9but (une seule comparaison), soit un temps constant O(1). Mais sans information particuli\u00e8re sur la distribution des donn\u00e9es, on retient le pire cas lin\u00e9aire. Pour donner un ordre d\u2019id\u00e9e, chercher un nom dans un annuaire de 30&nbsp;000 contacts en parcours s\u00e9quentiel n\u00e9cessitera au pire 30&nbsp;000 op\u00e9rations de comparaison \u2013 ce qui est faisable, mais si l\u2019annuaire passe \u00e0 des millions de contacts, cela devient beaucoup plus long.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Recherche dichotomique \u2013 Complexit\u00e9 O(log n)<\/h3>\n\n\n\n<p>Supposons maintenant que l\u2019on dispose d\u2019une liste <em>tri\u00e9e<\/em>. Peut-on chercher une valeur plus efficacement que de tout parcourir&nbsp;? Oui, gr\u00e2ce \u00e0 la <strong>recherche dichotomique<\/strong> (aussi appel\u00e9e recherche binaire). Le principe est de comparer la valeur cherch\u00e9e \u00e0 l\u2019\u00e9l\u00e9ment du milieu du tableau&nbsp;: si la valeur cible est plus petite, on sait qu\u2019elle se trouve dans la premi\u00e8re moiti\u00e9 (puisque le tableau est tri\u00e9)&nbsp;; si elle est plus grande, on ira chercher dans la seconde moiti\u00e9. En r\u00e9p\u00e9tant ce d\u00e9coupage en deux, on r\u00e9duit drastiquement le nombre de comparaisons. Voici une impl\u00e9mentation en Python&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def recherche_dichotomique(tableau, cible):\n    gauche = 0\n    droite = len(tableau) - 1\n    while gauche &lt;= droite:\n        milieu = (gauche + droite) \/\/ 2\n        if tableau&#91;milieu] == cible:\n            return milieu   # trouv\u00e9 \u00e0 l'indice milieu\n        elif tableau&#91;milieu] &lt; cible:\n            gauche = milieu + 1   # chercher dans la moiti\u00e9 droite\n        else:\n            droite = milieu - 1   # chercher dans la moiti\u00e9 gauche\n    return -1  # non trouv\u00e9\n<\/code><\/pre>\n\n\n\n<p>Dans cette boucle, \u00e0 chaque it\u00e9ration on divise par deux la portion de tableau dans laquelle la valeur peut se trouver. On passe ainsi d\u2019un espace de recherche de <em>n<\/em> \u00e9l\u00e9ments \u00e0 <em>n\/2<\/em>, puis <em>n\/4<\/em>, etc., jusqu\u2019\u00e0 \u00e9ventuellement trouver la valeur ou r\u00e9duire l\u2019espace \u00e0 z\u00e9ro. Le nombre d\u2019it\u00e9rations avant d\u2019arr\u00eater est d\u2019environ <strong>log\u2082(n)<\/strong> (logarithme en base 2 de <em>n<\/em>) dans le pire des cas. Autrement dit, la complexit\u00e9 de cet algorithme en temps est <strong>O(log n)<\/strong>. Pour reprendre l\u2019exemple de l\u2019annuaire de 30&nbsp;000 noms&nbsp;: une recherche dichotomique trouvera le nom en au plus 15 comparaisons environ (puisque 2^15 \u2248 32&nbsp;768), contre 30&nbsp;000 comparaisons pour la recherche lin\u00e9aire \u2013 un gain spectaculaire.<\/p>\n\n\n\n<p>Ci-dessous, une illustration montre comment la recherche dichotomique proc\u00e8de par divisions successives de l\u2019espace de recherche&nbsp;: \u00e0 chaque \u00e9tape, la moiti\u00e9 des \u00e9l\u00e9ments est \u00e9limin\u00e9e.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"563\" src=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png\" alt=\"\" class=\"wp-image-95\" srcset=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png 1000w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e-300x169.png 300w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e-768x432.png 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p><em>Exemple visuel de la recherche dichotomique (binary search) qui r\u00e9duit de moiti\u00e9 l\u2019espace de recherche \u00e0 chaque \u00e9tape. Les tableaux repr\u00e9sentent la portion restante \u00e0 chaque it\u00e9ration, jusqu\u2019\u00e0 trouver la valeur cible (27) \u00e0 l\u2019indice 5.<\/em><\/p>\n\n\n\n<p>Ainsi, la recherche dichotomique est extr\u00eamement efficace sur de grands volumes de donn\u00e9es tri\u00e9es. Cependant, elle n\u00e9cessite imp\u00e9rativement que la liste soit <strong>tri\u00e9e<\/strong> au pr\u00e9alable (ce qui, en soi, peut co\u00fbter du temps). Si les donn\u00e9es ne sont pas tri\u00e9es, on ne peut pas \u00e9liminer la moiti\u00e9 en un test, et la recherche s\u00e9quentielle O(n) reste la seule solution g\u00e9n\u00e9rale.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Boucles imbriqu\u00e9es \u2013 Complexit\u00e9 O(n\u00b2)<\/h3>\n\n\n\n<p>Consid\u00e9rons un algorithme dont les \u00e9tapes comportent <strong>deux boucles imbriqu\u00e9es<\/strong> parcourant chacune <em>n<\/em> \u00e9l\u00e9ments. Par exemple, une double boucle qui compare tous les couples d\u2019\u00e9l\u00e9ments dans un tableau, ou qui g\u00e9n\u00e8re une table de multiplication <em>n \u00d7 n<\/em>. Voici un petit exemple en Python&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def operations_quadratiques(n):\n    compteur = 0\n    for i in range(n):\n        for j in range(n):\n            compteur += 1   # op\u00e9ration constante O(1) dans la boucle interne\n    return compteur\n<\/code><\/pre>\n\n\n\n<p>Cette fonction effectue un incr\u00e9ment <code>compteur += 1<\/code> pour chaque paire <em>(i, j)<\/em> avec <em>i<\/em> allant de 0 \u00e0 <em>n-1<\/em> et <em>j<\/em> de 0 \u00e0 <em>n-1<\/em>. Il y a exactement <em>n \u00d7 n<\/em> it\u00e9rations au total, soit <em>n\u00b2<\/em> op\u00e9rations \u00e9l\u00e9mentaires. On en d\u00e9duit que la complexit\u00e9 en temps est <strong>O(n\u00b2)<\/strong> (croissance quadratique). En effet, le nombre d\u2019op\u00e9rations cro\u00eet comme le carr\u00e9 de <em>n<\/em>. Pour <em>n = 100<\/em>, on effectue 10&nbsp;000 incr\u00e9ments&nbsp;; pour <em>n = 1000<\/em>, un million d\u2019incr\u00e9ments, etc. De mani\u00e8re g\u00e9n\u00e9rale, si l\u2019on double <em>n<\/em>, le temps d\u2019ex\u00e9cution est multipli\u00e9 par ~4 (2\u00b2).<\/p>\n\n\n\n<p>De nombreux algorithmes ont un comportement quadratique, par exemple le <strong>tri \u00e0 bulles<\/strong> (qui compare tous les couples d\u2019\u00e9l\u00e9ments adjacents) ou le <strong>tri par insertion<\/strong> dans le pire cas. Au-del\u00e0 de quelques milliers d\u2019\u00e9l\u00e9ments, une complexit\u00e9 O(n\u00b2) peut devenir probl\u00e9matique, car le temps de calcul augmente tr\u00e8s vite. Par exemple, un algorithme en <em>n\u00b2<\/em> qui prend 1 seconde pour <em>n = 10&nbsp;000<\/em> \u00e9l\u00e9ments en prendra environ 4 secondes pour <em>n = 20&nbsp;000<\/em>, ~100 secondes pour <em>n = 100&nbsp;000<\/em>, et deviendra carr\u00e9ment impraticable pour <em>n = 1&nbsp;000&nbsp;000<\/em> (un million) d\u2019\u00e9l\u00e9ments (o\u00f9 <em>n\u00b2 = 10^12<\/em> op\u00e9rations). D\u2019o\u00f9 l\u2019importance de chercher des algorithmes plus efficients lorsque <em>n<\/em> devient grand.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Multiplication de matrices \u2013 O(n\u00b3) vs algorithme de Strassen (~O(n^2.8))<\/h3>\n\n\n\n<p>Pour illustrer une complexit\u00e9 <strong>cubique<\/strong> O(n\u00b3) et voir comment on peut parfois la r\u00e9duire, penchons-nous sur la multiplication de matrices carr\u00e9es de taille <em>n \u00d7 n<\/em>. L\u2019algorithme standard (appris en math\u00e9matiques) multiplie deux matrices <em>A<\/em> et <em>B<\/em> en calculant tous les produits scalaires entre lignes de <em>A<\/em> et colonnes de <em>B<\/em>. En pseudo-code, cela donne trois boucles imbriqu\u00e9es&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def multiplication_matrices(A, B):\n    n = len(A)\n    C = &#91;&#91;0] * n for _ in range(n)]\n    for i in range(n):\n        for j in range(n):\n            for k in range(n):\n                C&#91;i]&#91;j] += A&#91;i]&#91;k] * B&#91;k]&#91;j]\n    return C\n<\/code><\/pre>\n\n\n\n<p>Ici, les indices <em>i<\/em> et <em>j<\/em> parcourent respectivement les lignes et colonnes du r\u00e9sultat <em>C<\/em>, et la boucle <em>k<\/em> accumule le produit des \u00e9l\u00e9ments correspondants de la i-\u00e8me ligne de <em>A<\/em> et de la j-\u00e8me colonne de <em>B<\/em>. Le nombre d\u2019op\u00e9rations \u00e9l\u00e9mentaires (multiplications et additions) effectu\u00e9es est d\u2019environ <em>n<\/em> \u00d7 <em>n<\/em> \u00d7 <em>n<\/em> = <strong>n\u00b3<\/strong>. Donc la complexit\u00e9 en temps de l\u2019algorithme na\u00eff de multiplication de deux matrices de dimension <em>n<\/em> est <strong>\u0398(n\u00b3)<\/strong>. Pour donner un ordre de grandeur, multiplier deux matrices 100\u00d7100 n\u00e9cessite de l\u2019ordre de 1&nbsp;000&nbsp;000 d\u2019op\u00e9rations, et des matrices 1000\u00d71000 en n\u00e9cessitent 1&nbsp;000&nbsp;000&nbsp;000 (un milliard). On comprend qu\u2019am\u00e9liorer cet ordre de complexit\u00e9 serait pr\u00e9cieux pour le calcul scientifique ou le traitement d\u2019images par exemple, o\u00f9 les matrices peuvent \u00eatre tr\u00e8s grandes.<\/p>\n\n\n\n<p>De fait, il existe des algorithmes plus rapides que <em>\u0398(n\u00b3)<\/em> pour la multiplication matricielle. Le premier a \u00e9t\u00e9 d\u00e9couvert par <strong>Volker Strassen<\/strong> en 1969&nbsp;: l\u2019<strong>algorithme de Strassen<\/strong> utilise une approche r\u00e9cursive ing\u00e9nieuse. Son id\u00e9e est de d\u00e9couper les matrices en sous-matrices (de taille n\/2 \u00d7 n\/2) et de r\u00e9duire le nombre de multiplications n\u00e9cessaires en combinant astucieusement les r\u00e9sultats. Alors que l\u2019approche na\u00efve multiplie 8 sous-matrices (pour calculer les 4 blocs du r\u00e9sultat), Strassen parvient \u00e0 n\u2019en multiplier que 7, au prix de quelques additions suppl\u00e9mentaires. Ce gain de 1 multiplication peut para\u00eetre anodin, mais en r\u00e9appliquant la m\u00e9thode r\u00e9cursivement, le <strong>nombre total d\u2019op\u00e9rations<\/strong> suit une r\u00e9currence&nbsp;: <em>T(n) = 7 T(n\/2) + O(n\u00b2)<\/em> (les <em>O(n\u00b2)<\/em> proviennent des additions de matrices). R\u00e9soudre cette r\u00e9currence (par le <em>Master Theorem<\/em>, que l\u2019on verra plus loin) donne un ordre asymptotique d\u2019environ <strong>O(n^log27)<\/strong>, soit <strong>O(n^2.8074\u2026)<\/strong>. Ainsi, l\u2019algorithme de Strassen a une complexit\u00e9 inf\u00e9rieure \u00e0 n\u00b3. En pratique, cela signifie que pour des matrices tr\u00e8s grandes, Strassen sera plus rapide que l\u2019algorithme classique. Par exemple, pour n = 1024, <em>n\u00b3 \u2248 1,07\u00d710^9<\/em> op\u00e9rations tandis que <em>n^2.807<\/em> \u2248 4.7\u00d710^8*&nbsp;: presque deux fois moins.<\/p>\n\n\n\n<p>L\u2019algorithme de Strassen marque le d\u00e9but d\u2019une longue s\u00e9rie de recherches en algorithmique. Depuis 1969, d\u2019autres m\u00e9thodes de multiplication de matrices encore plus rapides (mais de plus en plus complexes) ont \u00e9t\u00e9 d\u00e9couvertes. L\u2019exposant de complexit\u00e9 a ainsi \u00e9t\u00e9 progressivement abaiss\u00e9&nbsp;: 2.80, 2.78, 2.67, \u2026 jusqu\u2019\u00e0 environ <strong>2.37<\/strong> aujourd\u2019hui. Autrement dit, on sait th\u00e9oriquement multiplier deux matrices en <em>O(n^2.37)<\/em> environ, gr\u00e2ce \u00e0 des algorithmes tr\u00e8s sophistiqu\u00e9s. Cependant, ces am\u00e9liorations extr\u00eames \u2013 parfois qualifi\u00e9es d\u2019<strong>algorithmes galactiques<\/strong> \u2013 ne sont <strong>pas utilis\u00e9es en pratique<\/strong>. En effet, ils ne deviennent avantageux qu\u2019\u00e0 des tailles de matrices astronomiquement grandes, et leur overhead (constantes cach\u00e9es, complexit\u00e9 d\u2019impl\u00e9mentation) les rend plus lents sur les matrices de taille courante. En pratique, l\u2019algorithme de Strassen lui-m\u00eame n\u2019est utile que pour des matrices au-del\u00e0 d\u2019un certain seuil (typiquement quelques centaines ou milliers)&nbsp;; en-de\u00e7\u00e0, le classique triple boucle peut \u00eatre plus rapide \u00e0 cause des optimisations CPU\/cache. Cet exemple illustre qu\u2019une meilleure complexit\u00e9 asymptotique n\u2019est pas toujours synonyme de meilleure performance r\u00e9elle sur des inputs de taille mod\u00e9r\u00e9e \u2013 mais \u00e0 tr\u00e8s grande \u00e9chelle, elle finit par l\u2019emporter. Quoi qu\u2019il en soit, la d\u00e9couverte de Strassen fut fondamentale car elle a d\u00e9montr\u00e9 que la borne <em>n\u00b3<\/em> n\u2019\u00e9tait pas une barri\u00e8re absolue, ouvrant tout un champ de recherche en algorithmique.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pr\u00e9sentation du Master Theorem (Th\u00e9or\u00e8me du Ma\u00eetre)<\/h2>\n\n\n\n<p>La r\u00e9solution de la r\u00e9currence de l\u2019algorithme de Strassen ci-dessus nous am\u00e8ne \u00e0 un outil pr\u00e9cieux en analyse d\u2019algorithmes&nbsp;: le <strong>Master Theorem<\/strong> (ou <em>th\u00e9or\u00e8me du ma\u00eetre<\/em>). Il s\u2019agit d\u2019un th\u00e9or\u00e8me qui donne, sans effort de calcul it\u00e9ratif, l\u2019ordre de grandeur asymptotique des solutions de r\u00e9currences divide-and-conquer courantes. De nombreux algorithmes r\u00e9cursifs divisent en effet le probl\u00e8me en plusieurs sous-probl\u00e8mes plus petits. Le Master Theorem consid\u00e8re les r\u00e9currences de la forme :<\/p>\n\n\n\n<p>T(n)=a\u2005\u200aT\u2009\u2063(nb)+f(n),T(n) = a \\; T\\!\\Big(\\frac{n}{b}\\Big) + f(n),<\/p>\n\n\n\n<p>o\u00f9 <em>a \u2265 1<\/em> est le nombre de sous-probl\u00e8mes, <em>b &gt; 1<\/em> le facteur de r\u00e9duction de la taille (chaque sous-probl\u00e8me a une taille ~<em>n\/b<\/em>), et <em>f(n)<\/em> le co\u00fbt hors r\u00e9cursion (temps pour diviser\/recombiner les sous-probl\u00e8mes). Intuitivement, on a un <strong>arbre de r\u00e9cursion<\/strong> de hauteur ~log_b(n) o\u00f9 \u00e0 chaque niveau les <em>a^k<\/em> appels de ce niveau traitent des probl\u00e8mes de taille <em>n\/b^k<\/em>. Le th\u00e9or\u00e8me du ma\u00eetre fournit une solution asymptotique <em>T(n) = \u0398(g(n))<\/em> selon la comparaison entre <em>f(n)<\/em> et <em>nlogba<\/em>, qui repr\u00e9sente (\u00e0 un facteur pr\u00e8s) le co\u00fbt total de tous les sous-probl\u00e8mes. On d\u00e9finit pour cela l\u2019<strong>exposant critique<\/strong> <em>c = log_b(a)<\/em> (aussi not\u00e9 <em>ccritique<\/em>). Trois cas se pr\u00e9sentent&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cas 1\u00a0:<\/strong> <em>f(n)<\/em> est <em>\u00ab\u00a0petit\u00a0\u00bb<\/em> par rapport \u00e0 <em>n^c<\/em>. Plus pr\u00e9cis\u00e9ment, si <em>f(n) = O(nc &#8211; \u03b5)<\/em> pour une certaine constante <em>\u03b5 > 0<\/em> (c\u2019est-\u00e0-dire <em>f(n)<\/em> est asymptotiquement plus petit que <em>n^c<\/em> \u00e0 un facteur polynomial pr\u00e8s), alors les sous-probl\u00e8mes dominent le co\u00fbt et on a\u00a0:<\/li>\n<\/ul>\n\n\n\n<p>T(n)=\u0398(nc).T(n) = \u0398\\big(n^c\\big).<\/p>\n\n\n\n<p><em>(Intuition&nbsp;: le travail est domin\u00e9 par les feuilles de l\u2019arbre de r\u00e9cursion, donc \u00e9quivalent au co\u00fbt des alog_b n = n^c sous-probl\u00e8mes de taille 1.)<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cas 2\u00a0:<\/strong> <em>f(n)<\/em> est de m\u00eame ordre que <em>n^c<\/em> (\u00e0 un facteur polylog pr\u00e8s). Si <em>f(n) = \u0398(n^c \u00b7 (\\log n)^k)<\/em> pour un certain <em>k \u2265 0<\/em> (incluant le cas <em>f(n) = \u0398(n^c)<\/em>), alors les co\u00fbts se r\u00e9partissent \u00e9quilibr\u00e9s entre la partie r\u00e9cursive et la partie <em>f(n)<\/em>, et on obtient\u00a0:<\/li>\n<\/ul>\n\n\n\n<p>T(n)=\u0398(nc(log\u2061n)\u2009k+1).T(n) = \u0398\\big(n^c (\\log n)^{\\,k+1}\\big).<\/p>\n\n\n\n<p><em>(Intuition&nbsp;: le travail total est la somme de contributions \u00e9quivalentes \u00e0 chaque niveau de l\u2019arbre, sur ~log n niveaux.)<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cas 3\u00a0:<\/strong> <em>f(n)<\/em> est <em>\u00ab\u00a0grand\u00a0\u00bb<\/em> par rapport \u00e0 <em>n^c<\/em>. Plus formellement, si <em>f(n) = \u03a9(nc + \u03b5)<\/em> pour une constante <em>\u03b5 > 0<\/em> \u2013 et sous une condition technique dite de <em>r\u00e9gularit\u00e9<\/em> garantissant que f ne cro\u00eet pas trop plus vite que <em>n^c<\/em> (condition souvent v\u00e9rifi\u00e9e dans les cas usuels) \u2013 alors c\u2019est <em>f(n)<\/em> qui domine et on a\u00a0:<\/li>\n<\/ul>\n\n\n\n<p>T(n)=\u0398(f(n)).T(n) = \u0398\\big(f(n)\\big).<\/p>\n\n\n\n<p><em>(Intuition&nbsp;: le co\u00fbt hors r\u00e9cursion \u00e0 la racine de l\u2019arbre (et peut-\u00eatre aux premiers niveaux) l\u2019emporte sur le co\u00fbt combin\u00e9 de tous les sous-probl\u00e8mes.)<\/em><\/p>\n\n\n\n<p>En appliquant le Master Theorem, on peut ainsi obtenir directement la complexit\u00e9 asymptotique sans d\u00e9rouler la r\u00e9currence niveau par niveau. Reprenons quelques <strong>exemples<\/strong> classiques d\u2019algorithmes divide-and-conquer&nbsp;: le <strong>tri fusion<\/strong> s\u2019analyse avec <em>a=2, b=2, f(n)=\u0398(n)<\/em> (fusion de deux tableaux tri\u00e9s)&nbsp;; ici <em>c = log\u20822 = 1<\/em> et <em>f(n)<\/em> est \u0398(n^1), donc cas 2 avec <em>k=0<\/em>&nbsp;: on obtient <em>T(n) = \u0398(n \u00b7 log n)<\/em>, bien connu pour le merge sort. Pour l\u2019<strong>algorithme de Strassen<\/strong> vu plus haut, <em>a=7, b=2, c = log\u20827 \u2248 2.807<\/em>, et <em>f(n)=O(n\u00b2)<\/em> \u00e9tait <em>O(n^{c &#8211; \u03b5})<\/em> (car 2 &lt; 2.807), on est dans le cas&nbsp;1, d\u2019o\u00f9 <em>T(n) = \u0398(n^c)<\/em> = \u0398(n^2.807), coh\u00e9rent avec le r\u00e9sultat annonc\u00e9. Un dernier exemple&nbsp;: la <strong>recherche dichotomique<\/strong> peut s\u2019exprimer par <em>T(n) = T(n\/2) + \u0398(1)<\/em> (une comparaison + orientation vers une moiti\u00e9)&nbsp;; ici <em>a=1, b=2, c=log\u20821 = 0<\/em>, et <em>f(n)=\u0398(1) = \u0398(n^0)<\/em> donc cas 2 (avec k=0)&nbsp;: on retrouve <em>T(n) = \u0398((n^0) \u00b7 log n) = \u0398(log n)<\/em>.<\/p>\n\n\n\n<p>Visuellement, on peut interpr\u00e9ter le Master Theorem \u00e0 l\u2019aide de l\u2019arbre de r\u00e9cursion \u00e9voqu\u00e9&nbsp;:<\/p>\n\n\n\n<p><em>Sch\u00e9ma d\u2019un arbre de r\u00e9cursion pour un algorithme divisant chaque probl\u00e8me en <strong>a<\/strong> sous-probl\u00e8mes de taille ~1\/<strong>b<\/strong> (ici illustr\u00e9 abstraitement). Le th\u00e9or\u00e8me du ma\u00eetre compare le co\u00fbt total des feuilles (nombre de n\u0153uds terminals ~nlogba) avec le co\u00fbt total de la racine et des niveaux interm\u00e9diaires (par rapport \u00e0 f(n)).<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"487\" src=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/001a3646-ed5f-41cf-a082-b92a2e4745f9.png\" alt=\"\" class=\"wp-image-94\" srcset=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/001a3646-ed5f-41cf-a082-b92a2e4745f9.png 1000w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/001a3646-ed5f-41cf-a082-b92a2e4745f9-300x146.png 300w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/001a3646-ed5f-41cf-a082-b92a2e4745f9-768x374.png 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>Le <strong>Master Theorem<\/strong> est un outil tr\u00e8s pratique pour analyser des algorithmes r\u00e9cursifs comme&nbsp;: tri fusion, tri rapide (quicksort), recherche binaire, exponentiation rapide, algorithms de divide-and-conquer divers (multiplication de grandes entiers, transform\u00e9e de Fourier rapide, etc.). Il ne couvre pas tous les types de r\u00e9currences (certaines n\u00e9cessitent des variantes ou d\u2019autres m\u00e9thodes, e.g. m\u00e9thode d\u2019Akra-Bazzi, r\u00e9solution par expansion en arbre, etc.), mais dans de nombreux cas courants il permet d\u2019obtenir imm\u00e9diatement la complexit\u00e9 asymptotique. Il est important de bien identifier <em>a<\/em>, <em>b<\/em> et <em>f(n)<\/em> puis d\u2019appliquer le cas correspondant. Avec un peu de pratique, on d\u00e9veloppe une <strong>intuition<\/strong> : par exemple, si <em>f(n)<\/em> est <em>n^c<\/em> polynomiale et domine la formule de recombinaison, on pressent directement un cas&nbsp;3 (co\u00fbt domin\u00e9 par f(n)); si <em>f(n)<\/em> est lin\u00e9aire et qu\u2019on a deux sous-appels moiti\u00e9 taille, on anticipe un cas 2 donnant <em>n log n<\/em>, etc. Cette capacit\u00e9 \u00e0 estimer rapidement la complexit\u00e9 vient avec l\u2019habitude et gr\u00e2ce \u00e0 des outils comme le Master Theorem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comparatif des ordres de complexit\u00e9<\/h2>\n\n\n\n<p>La complexit\u00e9 d\u2019un algorithme influe directement sur son temps d\u2019ex\u00e9cution et sa faisabilit\u00e9 pratique, en particulier lorsque la taille des donn\u00e9es augmente. Il est instructif de <strong>comparer la croissance<\/strong> des principales fonctions de complexit\u00e9 courantes. Le graphique ci-dessous illustre l\u2019augmentation du co\u00fbt (en nombre d\u2019op\u00e9rations arbitraires) en fonction de <em>n<\/em> pour diff\u00e9rentes classes de complexit\u00e9&nbsp;: constante <strong>O(1)<\/strong>, logarithmique <strong>O(log n)<\/strong>, lin\u00e9aire <strong>O(n)<\/strong>, quasi-lin\u00e9aire <strong>O(n log n)<\/strong>, quadratique <strong>O(n\u00b2)<\/strong> et exponentielle <strong>O(2^n)<\/strong>.<\/p>\n\n\n\n<p><em>Croissance compar\u00e9e (\u00e9chelle lin\u00e9aire) de diff\u00e9rentes fonctions de complexit\u00e9 en fonction de n (jusqu\u2019\u00e0 100). On observe que les fonctions <strong>lin\u00e9aire<\/strong> <code>O(n)<\/code> (courbe rouge) et <strong>n log n<\/strong> <code>O(n log n)<\/code> (rose) croissent mod\u00e9r\u00e9ment, alors que la fonction <strong>quadratique<\/strong> <code>O(n^2)<\/code> (bleu clair) monte bien plus rapidement. La fonction <strong>exponentielle<\/strong> <code>O(2^n)<\/code> (pointill\u00e9s violets) explose litt\u00e9ralement\u00a0: m\u00eame pour n = 20 elle d\u00e9passe 1\u00a0000\u00a0000 (ce qui la rend impraticable au-del\u00e0 de tr\u00e8s petites entr\u00e9es).<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"817\" src=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/4e659724-d989-43f7-b463-ac6a2081b375-1024x817.png\" alt=\"\" class=\"wp-image-93\" srcset=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/4e659724-d989-43f7-b463-ac6a2081b375-1024x817.png 1024w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/4e659724-d989-43f7-b463-ac6a2081b375-300x239.png 300w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/4e659724-d989-43f7-b463-ac6a2081b375-768x613.png 768w, https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/4e659724-d989-43f7-b463-ac6a2081b375.png 1484w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>On constate sur ce visuel que :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Une complexit\u00e9 <strong>constante<\/strong> O(1) (courbe orange, confondue avec l\u2019axe des x sur le graphe) est ind\u00e9pendante de <em>n<\/em> \u2013 c\u2019est l\u2019id\u00e9al, mais rare sur des probl\u00e8mes non triviaux. Par exemple acc\u00e9der \u00e0 un \u00e9l\u00e9ment dans un tableau par son index est une op\u00e9ration O(1).<\/li>\n\n\n\n<li>Une complexit\u00e9 <strong>logarithmique<\/strong> O(log n) (courbe orange fonc\u00e9) cro\u00eet tr\u00e8s lentement\u00a0: doubler <em>n<\/em> n\u2019augmente le co\u00fbt que de fa\u00e7on additive. La recherche dichotomique en est un exemple typique. Pour <em>n = 1\u00a0000\u00a0000<\/em>, log\u2082(n) \u2248 20\u00a0: un algorithme O(log n) ferait environ 20 \u00e9tapes, ce qui est excellent.<\/li>\n\n\n\n<li>Une complexit\u00e9 <strong>lin\u00e9aire<\/strong> O(n) (courbe rouge) cro\u00eet proportionnellement\u00a0: si on double <em>n<\/em>, le temps double. C\u2019est souvent acceptable pour des <em>n<\/em> assez grands (par ex., parcourir 1 million d\u2019\u00e9l\u00e9ments prend un temps proportionnel \u00e0 1 million). De nombreux algorithmes sont lin\u00e9aires (parcours de liste, somme de n nombres, recherche dans un tableau non tri\u00e9, etc.).<\/li>\n\n\n\n<li>Une complexit\u00e9 <strong>quasi-lin\u00e9aire<\/strong> O(n log n) (courbe rose) est l\u00e9g\u00e8rement plus co\u00fbteuse que lin\u00e9aire\u00a0: elle ajoute un facteur log. Les meilleurs algorithmes de tri g\u00e9n\u00e9raux (tri fusion, tri rapide moyen) sont en <em>O(n log n)<\/em>. Pour <em>n = 1\u00a0000\u00a0000<\/em>, <em>n log\u2082 n<\/em> \u2248 20\u00a0000\u00a0000 (20 millions), ce qui reste faisable en quelques secondes sur un PC moderne.<\/li>\n\n\n\n<li>Une complexit\u00e9 <strong>quadratique<\/strong> O(n\u00b2) (courbe bleu clair) devient lourde pour des <em>n<\/em> \u00e9lev\u00e9s. Si on multiplie <em>n<\/em> par 10, le temps est multipli\u00e9 par 100. Un algorithme en n\u00b2 qui traite 10\u00a0000 \u00e9l\u00e9ments en 1 seconde en mettra 100 secondes pour 100\u00a0000 \u00e9l\u00e9ments (plus d\u2019une minute), et ainsi de suite. Les double-boucles imbriqu\u00e9es m\u00e8nent souvent \u00e0 O(n\u00b2). Il faut faire attention d\u00e8s que <em>n<\/em> d\u00e9passe quelques milliers.<\/li>\n\n\n\n<li>Une complexit\u00e9 <strong>exponentielle<\/strong> O(2^n) (pointill\u00e9s violets) est <em>explosive<\/em>\u00a0: le temps de calcul double \u00e0 chaque \u00e9l\u00e9ment additionnel. Un algorithme en 2^n est pratiquement inutilisable au-del\u00e0 de n = 40 ou 50 (2^50 \u2248 1\u00a0quadrillion \u2248 10^15 op\u00e9rations). Des probl\u00e8mes d\u2019optimisation par force brute (voyageur de commerce, etc.) ou d\u2019\u00e9num\u00e9ration exhaustive ont des complexit\u00e9s exponentielles. Il n\u2019est g\u00e9n\u00e9ralement pas envisageable de traiter exhaustivement des grandes instances de tels probl\u00e8mes \u2013 on cherche alors des heuristiques, des approximations, ou on restreint la taille de <em>n<\/em>.<\/li>\n<\/ul>\n\n\n\n<p>\u00c0 titre d\u2019exemple chiffr\u00e9 pour comparer O(n) et O(log n)&nbsp;: pour n = 30&nbsp;000, une algorithme en <strong>O(n)<\/strong> effectuera ~30&nbsp;000 op\u00e9rations, alors qu\u2019un algorithme en <strong>O(log n)<\/strong> en fera environ log\u2082(30000) \u2248 15. L\u2019\u00e9cart se creuse encore plus pour des n plus grands. En revanche, entre un algorithme O(n) et un autre O(n log n), la diff\u00e9rence n\u2019est pas flagrante sur des tailles mod\u00e9r\u00e9es (disons n \u2264 quelques milliers), mais devient significative pour des millions d\u2019\u00e9l\u00e9ments (le facteur log n commence \u00e0 peser). Quant aux algorithmes quadratiques ou pires, ils deviennent rapidement prohibitif en temps de calcul d\u00e8s que n grandit. C\u2019est pourquoi en pratique, un d\u00e9veloppeur cherchera \u00e0 \u00e9viter les algorithmes exponentiels ou quadratiques sur de grandes entr\u00e9es, et privil\u00e9giera des solutions en temps lin\u00e9aire ou n log n si possible. Lorsqu\u2019un probl\u00e8me semble n\u00e9cessiter une complexit\u00e9 exponentielle, cela sugg\u00e8re souvent qu\u2019il appartient \u00e0 une classe de probl\u00e8mes intractables (en tout cas \u00e0 grande \u00e9chelle)&nbsp;: on entre alors dans le domaine de la complexit\u00e9 computationnelle (probl\u00e8mes NP-complets, etc., pour lesquels on pense qu\u2019aucune solution polynomialement efficace n\u2019existe).<\/p>\n\n\n\n<p>En r\u00e9sum\u00e9, <strong>ma\u00eetriser la complexit\u00e9<\/strong> permet de pr\u00e9voir le comportement d\u2019un algorithme quand les donn\u00e9es augmentent et d\u2019adapter ses choix en cons\u00e9quence. La diff\u00e9rence entre un algorithme O(n log n) et O(n\u00b2) peut d\u00e9terminer si une application passe \u00e0 l\u2019\u00e9chelle ou s\u2019effondre lorsque n cro\u00eet. D\u2019o\u00f9 l\u2019importance, pour un informaticien, de bien comprendre ces ordres de grandeur.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion \u2013 L\u2019importance de la complexit\u00e9 en pratique<\/h2>\n\n\n\n<p>La complexit\u00e9 algorithmique n\u2019est pas qu\u2019une notion th\u00e9orique&nbsp;: elle a un impact direct et concret sur les performances des logiciels. En d\u00e9veloppement, analyser la complexit\u00e9 des diff\u00e9rentes solutions possibles permet de <strong>choisir l\u2019algorithme le plus adapt\u00e9<\/strong> \u00e0 son probl\u00e8me et \u00e0 ses contraintes. Par exemple, pour manipuler un petit tableau de 100 \u00e9l\u00e9ments, un algorithme O(n\u00b2) peut tr\u00e8s bien suffire et sa simplicit\u00e9 de code peut \u00eatre un atout. Mais si l\u2019application doit g\u00e9rer des millions d\u2019enregistrements, il faudra absolument une m\u00e9thode plus efficiente (O(n log n) ou O(n) selon le cas) faute de quoi le temps de r\u00e9ponse deviendra inacceptable. De m\u00eame, en algorithmique avanc\u00e9e, comprendre la complexit\u00e9 aide \u00e0 identifier les <strong>goulets d\u2019\u00e9tranglement<\/strong> et \u00e0 concentrer les optimisations sur les parties critiques du code.<\/p>\n\n\n\n<p>En pratique, les ing\u00e9nieurs utilisent l\u2019analyse de complexit\u00e9 conjointement avec des tests empiriques (mesures de temps) pour valider les performances. La complexit\u00e9 donne une <strong>tendance asymptotique<\/strong> ind\u00e9pendante du mat\u00e9riel, tandis que les benchmarks mesurent le temps r\u00e9el en incluant les constantes, effets de cache, etc. Les deux se compl\u00e8tent pour pr\u00e9voir le comportement d\u2019un programme. Notons aussi que la complexit\u00e9 en <strong>espace<\/strong> peut \u00eatre d\u00e9terminante&nbsp;: sur des syst\u00e8mes embarqu\u00e9s \u00e0 m\u00e9moire limit\u00e9e, un algorithme l\u00e9g\u00e8rement plus lent en temps mais bien plus \u00e9conome en m\u00e9moire peut \u00eatre pr\u00e9f\u00e9r\u00e9.<\/p>\n\n\n\n<p>Enfin, l\u2019\u00e9tude de la complexit\u00e9 sensibilise aux limites de l\u2019informatique. Elle met en lumi\u00e8re des probl\u00e8mes pour lesquels <em>aucun<\/em> algorithme efficace n\u2019est connu (par exemple le fameux probl\u00e8me NP-complet du voyageur de commerce qui, en brute force, cro\u00eet en O(n!)). Elle encourage \u00e9galement la recherche de nouvelles m\u00e9thodes&nbsp;: c\u2019est en tentant d\u2019am\u00e9liorer la complexit\u00e9 qu\u2019ont \u00e9t\u00e9 invent\u00e9s des algorithmes r\u00e9volutionnaires (tri rapide, algorithme de Dijkstra, compression de donn\u00e9es, etc.). Pour aller plus loin, on pourra consulter des ressources comme le classique <strong>\u201cThe Art of Computer Programming\u201d de Donald Knuth<\/strong>, qui aborde en profondeur l\u2019analyse des algorithmes et des structures de donn\u00e9es, ou encore les nombreux articles et cours en ligne (par ex. sur <strong>GeeksforGeeks<\/strong> ou <strong>Wikip\u00e9dia<\/strong>) consacr\u00e9s aux diff\u00e9rents algorithmes et \u00e0 leur complexit\u00e9. La plateforme <strong>ArXiv<\/strong> regorge \u00e9galement de publications de recherche en algorithmique qui poussent toujours plus loin les fronti\u00e8res (par ex. les derni\u00e8res avanc\u00e9es sur la multiplication de matrices, la r\u00e9solution d\u2019instances NP-difficiles, etc.). En somme, la complexit\u00e9 algorithmique est un aspect fondamental de la science informatique&nbsp;: en \u00eatre conscient et savoir l\u2019estimer donne un v\u00e9ritable <strong>pouvoir pr\u00e9dictif<\/strong> et contribue \u00e0 \u00e9crire du code \u00e0 la fois \u00e9l\u00e9gant et efficace, capable de relever les d\u00e9fis des donn\u00e9es massives de notre \u00e9poque.<\/p>\n\n\n\n<p><strong>Sources et pour approfondir&nbsp;:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Wikip\u00e9dia \u2013 <em>Complexit\u00e9 en temps<\/em>, <em>Complexit\u00e9 en espace<\/em>, <em>Notation Big O<\/em>, <em>Th\u00e9orie de la complexit\u00e9<\/em>, etc.. Des articles d\u00e9taill\u00e9s couvrent chaque notion pr\u00e9sent\u00e9e.<\/li>\n\n\n\n<li>GeeksforGeeks \u2013 Tutoriels en anglais sur l\u2019analyse de complexit\u00e9 et structures de donn\u00e9es (ex\u00a0: \u201cBig-O vs Theta vs Omega Notations\u201d, \u201cMaster Theorem\u201d etc.), avec de nombreux exemples de code.<\/li>\n\n\n\n<li><strong>The Art of Computer Programming<\/strong>, vol.\u00a01 (D. Knuth) \u2013 Chapitres 1 et 2 sur les algorithmes fondamentaux, contenant une pr\u00e9sentation rigoureuse de l\u2019analyse de complexit\u00e9 et de nombreux exemples classiques.<\/li>\n\n\n\n<li>Cormen et al., <strong>Introduction to Algorithms<\/strong> \u2013 Livre de r\u00e9f\u00e9rence couvrant l\u2019analyse d\u2019algorithmes (contient le Master Theorem, exemples de complexit\u00e9, etc.).<\/li>\n\n\n\n<li>Ressources en ligne (cours, PDF) \u2013 Par ex. le cours <em>\u201cAlgorithmique\u00a0: Notion de complexit\u00e9\u201d<\/em> de l\u2019UPMC, ou les notes de <strong>Sylvain Perifel, <em>Complexit\u00e9 algorithmique<\/em>, Ellipses 2014<\/strong>, pour une approche plus math\u00e9matique.<\/li>\n\n\n\n<li>Articles de recherche (sur <em>arXiv<\/em>) \u2013 Pour les passionn\u00e9s, suivre les d\u00e9veloppements sur des sujets pointus (par ex. l\u2019algorithme de multiplication de matrices de V. Vassilevska Williams, etc.) permet de voir comment on repousse les limites de la complexit\u00e9 dans des domaines sp\u00e9cifiques.<\/li>\n<\/ul>\n\n\n\n<p>Toutes ces ressources vous permettront d\u2019approfondir vos connaissances et de d\u00e9couvrir de nouveaux exemples. La complexit\u00e9 algorithmique est un domaine riche et en constante \u00e9volution&nbsp;: en la ma\u00eetrisant, vous acqu\u00e9rez une cl\u00e9 pour concevoir des programmes performants et mieux comprendre ce que la machine peut (ou ne peut pas) accomplir dans un temps donn\u00e9. Bonne exploration&nbsp;!<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Complexit\u00e9 Algorithmique\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/MpvUM1e69Y0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction \u2013 Complexit\u00e9 algorithmique vs th\u00e9orie de la complexit\u00e9 En informatique, l\u2019analyse de la complexit\u00e9&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[4],"tags":[],"class_list":["post-92","post","type-post","status-publish","format-standard","hentry","category-informatique"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou\" \/>\n<meta property=\"og:description\" content=\"Introduction \u2013 Complexit\u00e9 algorithmique vs th\u00e9orie de la complexit\u00e9 En informatique, l\u2019analyse de la complexit\u00e9&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/\" \/>\n<meta property=\"og:site_name\" content=\"Le site du matou\" \/>\n<meta property=\"article:published_time\" content=\"2025-06-07T12:11:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-07T12:31:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"563\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"admin2154\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin2154\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"27 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/\",\"url\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/\",\"name\":\"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou\",\"isPartOf\":{\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png\",\"datePublished\":\"2025-06-07T12:11:28+00:00\",\"dateModified\":\"2025-06-07T12:31:20+00:00\",\"author\":{\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/d62778c4a9a9eb68b258ce862c5cb052\"},\"breadcrumb\":{\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage\",\"url\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png\",\"contentUrl\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png\",\"width\":1000,\"height\":563},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/#website\",\"url\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/\",\"name\":\"Le site du matou\",\"description\":\"Un site utilisant WordPress ma foi pas si mal fichu que \u00e7a\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/d62778c4a9a9eb68b258ce862c5cb052\",\"name\":\"admin2154\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/30bc2ae54660b3c6a84a10d6da54e19248e82ef919e0a33feae1adf7d6e0a9c6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/30bc2ae54660b3c6a84a10d6da54e19248e82ef919e0a33feae1adf7d6e0a9c6?s=96&d=mm&r=g\",\"caption\":\"admin2154\"},\"sameAs\":[\"http:\/\/boissiz.cluster029.hosting.ovh.net\"],\"url\":\"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/author\/admin2154\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/","og_locale":"fr_FR","og_type":"article","og_title":"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou","og_description":"Introduction \u2013 Complexit\u00e9 algorithmique vs th\u00e9orie de la complexit\u00e9 En informatique, l\u2019analyse de la complexit\u00e9&hellip;","og_url":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/","og_site_name":"Le site du matou","article_published_time":"2025-06-07T12:11:28+00:00","article_modified_time":"2025-06-07T12:31:20+00:00","og_image":[{"width":1000,"height":563,"url":"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png","type":"image\/png"}],"author":"admin2154","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"admin2154","Dur\u00e9e de lecture estim\u00e9e":"27 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/","url":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/","name":"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance - Le site du matou","isPartOf":{"@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/#website"},"primaryImageOfPage":{"@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage"},"image":{"@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage"},"thumbnailUrl":"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png","datePublished":"2025-06-07T12:11:28+00:00","dateModified":"2025-06-07T12:31:20+00:00","author":{"@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/d62778c4a9a9eb68b258ce862c5cb052"},"breadcrumb":{"@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#primaryimage","url":"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png","contentUrl":"https:\/\/boissiebruno-pageperso-pi.ovh\/wp-content\/uploads\/2025\/06\/78113dfe-87c2-4d09-889d-d0b7a013e14e.png","width":1000,"height":563},{"@type":"BreadcrumbList","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/2025\/06\/07\/complexite-algorithmique-notions-exemples-et-importance\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/boissiebruno-pageperso-pi.ovh\/"},{"@type":"ListItem","position":2,"name":"Complexit\u00e9 Algorithmique\u00a0: Notions, Exemples et Importance"}]},{"@type":"WebSite","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/#website","url":"https:\/\/boissiebruno-pageperso-pi.ovh\/","name":"Le site du matou","description":"Un site utilisant WordPress ma foi pas si mal fichu que \u00e7a","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/boissiebruno-pageperso-pi.ovh\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Person","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/d62778c4a9a9eb68b258ce862c5cb052","name":"admin2154","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/boissiebruno-pageperso-pi.ovh\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/30bc2ae54660b3c6a84a10d6da54e19248e82ef919e0a33feae1adf7d6e0a9c6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/30bc2ae54660b3c6a84a10d6da54e19248e82ef919e0a33feae1adf7d6e0a9c6?s=96&d=mm&r=g","caption":"admin2154"},"sameAs":["http:\/\/boissiz.cluster029.hosting.ovh.net"],"url":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/author\/admin2154\/"}]}},"_links":{"self":[{"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/posts\/92","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/comments?post=92"}],"version-history":[{"count":1,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/posts\/92\/revisions"}],"predecessor-version":[{"id":96,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/posts\/92\/revisions\/96"}],"wp:attachment":[{"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/media?parent=92"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/categories?post=92"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boissiebruno-pageperso-pi.ovh\/index.php\/wp-json\/wp\/v2\/tags?post=92"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}