<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Algorithmie | Julien Maxant</title><link>https://www.julien-maxant.com/tags/algorithmie/</link><description>Articles, projets et veille sur le thème « Algorithmie ».</description><generator>Hugo -- gohugo.io</generator><language>fr-FR</language><copyright>2026 - Julien Maxant</copyright><lastBuildDate>Tue, 13 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.julien-maxant.com/tags/algorithmie/index.xml" rel="self" type="application/rss+xml"/><item><title>Briller en société grâce à Big O()</title><link>https://www.julien-maxant.com/blog/briller-en-societe-grace-a-big-o/</link><guid>https://www.julien-maxant.com/blog/briller-en-societe-grace-a-big-o/</guid><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><description>Pour celles et ceux qui (comme moi) sont perplexes quand ils ou elles lisent "this is O(n²), use a hashmap" sur Stack Overflow.</description><content:encoded><![CDATA[<p>La notation Big O, pour un profil comme le mien (j&rsquo;entends par là, un profil reconverti ou dont la formation initiale
n&rsquo;était pas orientée maths/informatique), c&rsquo;est un sujet un peu mystérieux qu&rsquo;on aperçoit sur des réponses Stack Overflow
ou des threads Reddit et face auquel on lève un sourcil et on prend l&rsquo;air inspiré de la personne qui n&rsquo;a pas vraiment
compris, mais préfère éviter que ce soit vu. <em>A posteriori</em>, je pense que ça se voit et que la plupart d&rsquo;entre nous ne
comprennent pas forcément beaucoup plus ce dont il s&rsquo;agit (un peu comme les regex).</p>
<p>Je me suis donc lancé (à corps perdu, rien de moins) dans le sujet pour pouvoir moi aussi briller en société et laisser
des commentaires de revue de code abscons (disclaimer : j&rsquo;ai passé un bac Littéraire, donc ne prenez pas ce que je dis
pour parole d&rsquo;évangile hein).</p>
<h2 id="que-sont-les-o">Que sont les &ldquo;O(&hellip;)&rdquo;</h2>
<p>Pour résumer rapidement, cette notation décrit comment le temps d&rsquo;exécution évolue lorsque la quantité de données (<code>n</code>)
augmente.</p>
<table>
	<thead>
			<tr>
					<th>Notation</th>
					<th>Nom</th>
					<th>Exemples (Go, PHP)</th>
					<th>Si n double…</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>O(1)</td>
					<td>Constant</td>
					<td><code>nombres[0]</code>, <code>$tableau[0]</code></td>
					<td>Temps identique</td>
			</tr>
			<tr>
					<td>O(log n)</td>
					<td>Logarithmique</td>
					<td><code>slices.BinarySearch()</code></td>
					<td>+1 étape</td>
			</tr>
			<tr>
					<td>O(n)</td>
					<td>Linéaire</td>
					<td><code>for range</code>, <code>foreach</code>, <code>in_array()</code></td>
					<td>Temps × 2</td>
			</tr>
			<tr>
					<td>O(n log n)</td>
					<td>Quasi-linéaire</td>
					<td><code>slices.Sort()</code>, <code>sort()</code>, <code>usort()</code></td>
					<td>Un peu plus que × 2</td>
			</tr>
			<tr>
					<td>O(n²)</td>
					<td>Quadratique</td>
					<td>Deux <code>for range</code> ou <code>foreach</code> imbriqués</td>
					<td>Temps × 4</td>
			</tr>
			<tr>
					<td>O(n³)</td>
					<td>Cubique</td>
					<td>Trois <code>for</code> ou <code>foreach</code> imbriqués</td>
					<td>Temps × 8</td>
			</tr>
			<tr>
					<td>O(2ⁿ)</td>
					<td>Exponentiel</td>
					<td>Fibonacci récursif naïf</td>
					<td>Temps au carré</td>
			</tr>
	</tbody>
</table>
<p>Si ça vous éclaire : bravo ! Vous êtes bien plus intelligent.e.s que moi, sinon, pas de panique, des explications
arrivent.</p>
<h2 id="approfondissons-avec-des-exemples-">Approfondissons (avec des exemples !)</h2>
<p>Ce que cette notation (et ce tableau) permet, c&rsquo;est d&rsquo;anticiper comment se comportera un algorithme selon la quantité
de données (<code>n</code>).</p>
<p>Les exemples qui suivent prendront des valeurs arbitraires pour la facilité de lecture : on partira du principe que
l&rsquo;opération coûtera 1ms (quelle qu&rsquo;elle soit).</p>
<h3 id="o1"><code>O(1)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient un élément</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">nombres</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="c1">// 1ms</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">nombres</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="c1">// 1ms</span></span></span></code></pre></div><p>Le temps d&rsquo;exécution est <strong>constant</strong> : on récupère un élément dans le tableau, et c&rsquo;est tout.</p>
<h3 id="olog-n"><code>O(log n)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments triés</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">slices</span><span class="p">.</span><span class="nf">BinarySearch</span><span class="p">(</span><span class="nx">nombres</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~10ms</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 000 éléments triés</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">slices</span><span class="p">.</span><span class="nf">BinarySearch</span><span class="p">(</span><span class="nx">nombres</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~20ms</span></span></span></code></pre></div><p>Bien que la quantité de données soit 1000 fois plus importante dans le second cas, le temps d&rsquo;exécution est seulement
multiplié par 2 : c&rsquo;est le principe de la recherche binaire.</p>
<p>Prenez <code>git bisect</code> (commande git qui mérite éloges et offrandes quotidiennes) : on lui donne un point de départ (<code>git bisect good</code>, traduisible par &ldquo;à ce moment, la prod marchait encore&rdquo;), un point d&rsquo;arrivée (<code>git bisect bad</code>, ou &ldquo;c&rsquo;est là que la prod a pris feu&rdquo;), et à partir de là, il va se mettre au milieu de l&rsquo;intervalle (<code>n</code>). À chaque itération, on teste, on définit si c&rsquo;est bon ou non, ce qui permet de déduire &ldquo;la bonne&rdquo; moitié, et il recommence à partir de la bonne moitié pour éliminer par dichotomie jusqu&rsquo;à arriver au point de bascule (le commit en cause).</p>
<p>Concrètement, ça veut dire qu&rsquo;au lieu de tester <em>chacun</em> des commits (soit <code>n</code>), on aura dans le pire des cas 10 ou 20 opérations (au lieu de 1 000 ou 1 000 000).</p>
<h3 id="on"><code>O(n)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nx">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">v</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="c1">// 1 000ms</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nx">total</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">v</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="c1">// 1 000 000ms</span></span></span></code></pre></div><p>Ici, c&rsquo;est explicite, le coût croît <strong>linéairement</strong> : le coût d&rsquo;exécution sera de <code>n</code> ms.</p>
<h3 id="on-log-n"><code>O(n log n)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">slices</span><span class="p">.</span><span class="nf">Sort</span><span class="p">(</span><span class="nx">nombres</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~10 000ms, soit 10s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nx">slices</span><span class="p">.</span><span class="nf">Sort</span><span class="p">(</span><span class="nx">nombres</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~20 000 000ms, soit ~5h30</span></span></span></code></pre></div><p>Celui-ci est un peu abstrait, car, que ce soit en PHP ou en Go, les algorithmes de tri (<code>sort</code> en php) fonctionnent sous le capot en <code>O(n log n)</code>, c&rsquo;est la complexité des bons algorithmes de tri (comme le tri fusion). Dans notre cas, ce qu&rsquo;il faut garder en tête, c&rsquo;est que le <code>log</code> grandit lentement : la différence entre un tri <code>O(n log n)</code> et un tri <code>O(n²)</code> sur 1 000 000 d&rsquo;éléments, c&rsquo;est la différence entre 5h30 et 32 ans.</p>
<h3 id="on-1"><code>O(n²)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// comparer nombres[i] et nombres[j]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="c1">// 1 000 000ms, soit ~17min</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// 1 000 000 000 000ms, soit ~32 ans</span></span></span></code></pre></div><p>L&rsquo;exemple ci-dessus est naïf (et encore une fois il s&rsquo;agit de donner un ordre d&rsquo;idée), mais c&rsquo;est le cas typique qui fonctionne <em>jusqu&rsquo;à un certain point</em> : une tâche de fond qui compare des contenus ou des entités et qui tourne sans problème, mais où l&rsquo;opération appliquée voit son coût augmenté de <code>2n</code> pour chaque nouvelle entité. Si on double le nombre d&rsquo;entités, le temps d&rsquo;exécution quadruple.</p>
<h3 id="on-2"><code>O(n³)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// nombres contient 100 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">nombres</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">   </span><span class="c1">// ...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="c1">// 1 000 000ms, soit ~17min</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// nombres contient 1 000 éléments</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// 1 000 000 000ms, soit ~11 jours et demi</span></span></span></code></pre></div><p>Dans ce cas, si on double le nombre d&rsquo;entités, le temps d&rsquo;exécution est multiplié par huit.</p>
<h3 id="o2ⁿ"><code>O(2ⁿ)</code></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">fib</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">return</span><span class="w"> </span><span class="nx">n</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nf">fib</span><span class="p">(</span><span class="nx">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nf">fib</span><span class="p">(</span><span class="nx">n</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">fib</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="c1">// 1ms</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">fib</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~1 000ms, soit ~1s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">fib</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~2 000ms, soit ~2s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">fib</span><span class="p">(</span><span class="mi">12</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~4 000ms, soit ~4s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">fib</span><span class="p">(</span><span class="mi">30</span><span class="p">)</span><span class="w"> </span><span class="c1">// ~1 000 000 000ms, soit ~12 jours</span></span></span></code></pre></div><p>Dans cet exemple, <code>n</code> n&rsquo;est plus un tableau, mais un entier arbitraire. Le principe s&rsquo;applique quand même : chaque incrémentation <strong>double le temps d&rsquo;exécution</strong> (d&rsquo;où <code>2ⁿ</code> soit <code>2 ^ 10</code>, puis <code>2 ^ 11</code> etc).</p>
<h2 id="et-ça-sert-à-quoi-">Et ça sert à quoi ?</h2>
<p>Déjà, ça ne sert pas <em>au quotidien</em>.</p>
<p>Quitte à évaluer les complexités rencontrées, au quotidien, on sera plus souvent confrontés à des complexités de tout autre ordre (NPath, cyclomatique par exemple) et qui seront bien plus contraignantes ou dangereuses sur le long terme ou dans la vie du projet car elles sous-entendent des problèmes de compréhension et de maintenance du code.</p>
<p>Il y a aussi le non-dit, qui est que dans bien des cas cette grille d&rsquo;analyse sera peu pertinente : comme pour nos amis les IA, le contexte est tout. Sur une volumétrie limitée par exemple, c&rsquo;est une analyse qui n&rsquo;apportera rien.</p>
<p>En revanche, c&rsquo;est un outil d&rsquo;anticipation et d&rsquo;architecture de son code : avoir tout ça en tête, c&rsquo;est pouvoir se poser la question &ldquo;Comment mon code se comportera quand il sera alimenté par <code>n</code> fois plus de données ?&rdquo;. Et c&rsquo;est aussi un raccourci et un vocabulaire commun plus précis, à défaut d&rsquo;être plus intelligible, pour mieux répondre ou mieux review le code.</p>
<p>Et pour ce qui est de briller en société : honnêtement, bof. Mais ça m&rsquo;aura au moins permis d&rsquo;écrire cet article, donc c&rsquo;est toujours ça de pris (je garde les regex sous le coude).</p>
]]></content:encoded></item></channel></rss>