English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

nu

invité
1 / ?
retour aux leçons

Les Taux De Croissance, Pas Les Coûts Absolus

O: Mesurer La Vitesse À Laquelle Les Coûts Croissent

La notation O mesure le taux de croissance du coût de l'algorithme — pas le coût absolu.

La question que répond O : à mesure que la taille de l'entrée N double, le travail double ? Quadruple ? Reste plat ?

Le 'O' signifie 'ordre de grandeur'. L'expression à l'intérieur des parenthèses décrit la forme de la courbe de croissance.

Tableau De Croissance O: opérations à N = 10, 100 et 1,000 pour O(1), O(N) et O(N²)

ClasseS De Complexité Clé :

- O(1) — constant : le coût ne croît pas. Exemple : rechercher une valeur par index dans un tableau. Que le tableau ait 10 éléments ou 10 millions, une recherche reste une recherche.

- O(N) — linéaire : le coût croît avec l'entrée. Exemple : lire chaque élément d'une liste une fois. Doublons la liste, doublons les lectures.

- O(N²) — quadratique : le coût croît en fonction du carré de l'entrée. Exemple : comparer chaque élément à chaque autre élément. Double N, quadruple le travail.

Tableau De Comparaison De La Croissance :

| N | O(1) | O(N) | O(N²) |

|---|------|------|-------|

| 10 | 1 | 10 | 100 |

| 100 | 1 | 100 | 10,000 |

| 1,000 | 1 | 1,000 | 1,000,000 |

À N = 10, la différence semble petite. À N = 1,000, l'écart devient immense.

Comparer O(N) À O(N²)

Utilisez le tableau de comparaison de la croissance ci-dessus.

À N = 1,000 : O(N) nécessite 1,000 opérations. O(N²) nécessite 1,000,000 opérations.

À N = 1,000, combien de fois plus d'opérations nécessite O(N²) par rapport à O(N) ? Montrez votre travail.

Comment la structure du code révèle la complexité

Comment identifier Big O à partir du code

Big O se cache dans la forme de votre code. Quatre modèles couvrent la plupart des cas :

Boucle unique parcourant N éléments : O(N)

# O(N) : une passe à travers la liste
for item in list_of_n_items:
    process(item)

Boucles imbriquées, chacune parcourant N éléments : O(N²)

# O(N²) : chaque élément est associé à chaque autre élément
for item_a in list_of_n_items:
    for item_b in list_of_n_items:
        compare(item_a, item_b)

Requête en temps constant : O(1)

Accès à un index d'ensemble, recherche dans un tableau hash — une étape indépendamment de la taille.

Diviser pour conquérir (couper le problème en deux à chaque étape) : O(log N)

Recherche binaire : chaque vérification divise les éléments restants par deux.

---

Big O caché : une liste à l'intérieur d'une boucle

# Ceci a l'air de O(N) mais il s'agit en réalité de O(N²)
visited = []
for item in list_of_n_items:
    if item not in visited:   # scanne tous les éléments de visited : O(N)
        visited.append(item)  # la boucle entière : O(N²)

La ligne if item not in visited effectue un scan de chaque élément de visited à chaque itération. Un scan de liste coûte O(N). Une boucle qui s'exécute N fois, chaque fois faisant O(N) de travail : O(N) × O(N) = O(N²).

Ce modèle apparaît dans plus de 1 000 projets open source. La solution nécessite une seule caractère : remplacer visited = [] par visited = set(). L'examen de l'appartenance à un ensemble coûte O(1) et non O(N). Une seule modification. Mêmes résultats. 1 000× plus rapide à N = 1 000.

Classifiez et corrigez ce code

Lisez ce code :

result = []
for name in student_names:
    if name not in result:
        result.append(name)
Quelle est la complexité Big O de ce code ? Expliquez pourquoi la ligne if name not in result rend le tout coûteux. Réécrivez ensuite le code pour qu'il soit en O(N).

Théorie et pratique

Big O dans la nature

Big O n'est pas seulement de la théorie. Elle sépare les programmes qui se terminent en quelques secondes de ceux qui prennent 17 minutes - sur la même tâche exacte.

Exemple réel : détection de cycles de dépendances dans un système de build.

Lorsque vous installez du logiciel, votre ordinateur résout un graphe des dépendances : paquet A a besoin de B, B a besoin de C, et ainsi de suite. Un système de build vérifie ce graphe pour y trouver des cycles.

Un algorithme de détection de cycles en O(N²) fonctionne parfaitement à N = 100 paquets. À N = 50 000 paquets (un projet réel) : cela prend 17 minutes. La solution en O(N) : 10 secondes.

Cette défectuosité exacte existe dans GHC (compilateur Haskell), pip (gestionnaire de packages Python), Maven (système de build Java), Cargo (gestionnaire de packages Rust) et dans + de 1 000 autres projets.

Pas parce que leurs auteurs étaient négligents. visited = [] a été écrit lorsque N était petit. Le code a calcifié. N a augmenté. Personne ne s'en est aperçu jusqu'à ce que la build prenne la moitié d'une heure.

Big O est le vocabulaire qui vous permet de nommer ce qui s'est produit - et de le corriger.

---

Souhaitez-vous aller plus loin ? Notre cours Unhamming inclut un chapitre complet sur Big O, MOAD-0001 (une véritable défaillance O(N²) trouvée dans 1 000 projets open-source), et pourquoi nommer un modèle vous permet de le trouver partout. Voir [Le chapitre manquant : Complexité algorithmique](/fr/un/unhamming_algorithmic_complexity).

Prédisez les temps de build

Un système de build utilise la détection de cycles en O(N²).

Temps de build mesurés :

- N = 100 paquets : 0,01 secondes

- N = 1 000 paquets : 1 seconde

Pour O(N²) : le temps varie en (N_new / N_old)².

Pour O(N) : le temps varie en (N_new / N_old).

En utilisant ces formules et des données mesurées : (A) à N = 10 000, combien de temps prend la version en O(N²) ? (B) après une correction en O(N), en prenant N = 1 000 comme point de référence, combien de temps prend la version en O(N) à N = 10 000 ? Montrez votre travail pour les deux.