La notation grand O depuis le début
Comprenez pourquoi la croissance asymptotique est importante, comment éliminer les constantes et les termes d’ordre inférieur, et comment lire instantanément la notation grand O.
La notation grand O depuis le début est une leçon Coding Interview Prep gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
Pourquoi mesurer l’efficacité d’un algorithme
Deux programmes peuvent être tous les deux corrects, alors que l’un termine en un clin d’œil et que l’autre s’exécute pendant des heures. La complexité temporelle décrit la façon dont le temps d’exécution augmente lorsque l’entrée grandit.
# O(n) approach
def find_max_linear(nums):
m = nums[0]
for n in nums:
if n > m: m = n
return m
# O(n^2) approach (unnecessary double loop)
def find_max_quadratic(nums):
for i in range(len(nums)):
is_max = all(nums[i] >= nums[j] for j in range(len(nums)))
if is_max: return nums[i]
print(find_max_linear([3, 1, 4, 1, 5, 9])) # 9Big-O : borne supérieure asymptotique
Big-O décrit la borne supérieure, dans le pire des cas, de la vitesse à laquelle le coût augmente. L’astuce consiste à supprimer les constantes et les termes plus petits, car seul le terme dominant compte à grande échelle. Consultez le code.
# T(n) = 3n^2 + 5n + 100 is O(n^2)
# because the n^2 term dominates for large n
# T(n) = 2n + 1000 is O(n)
# the constant 1000 becomes negligible
# Rule: drop constants and lower-order terms
# 5n^3 + 2n^2 + n + 1 => O(n^3)
# 100 * log(n) + n => O(n)
print('O(n^2) example: counting iterations')
n = 1000
count = sum(1 for i in range(n) for j in range(n))
print(count) # 1_000_000 = n^2Classes de complexité courantes
De la plus rapide à la plus lente : O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n), O(n!). Les connaître vous permet de choisir la bonne approche avant d’écrire une seule ligne.
import math
n = 1000
print(f'O(1): {1}')
print(f'O(log n): {int(math.log2(n))}')
print(f'O(n): {n}')
print(f'O(n log n): {int(n * math.log2(n))}')
print(f'O(n^2): {n**2}')
# O(2^n) for n=1000 is astronomically large
# O(n!) even largerSupprimer les constantes : pourquoi c’est important
Exécuter 5n étapes ou 2n étapes donne dans les deux cas O(n) — les constantes dépendent du matériel, pas de l’algorithme. La notation grand O les supprime afin de comparer la croissance sur une base équitable.
# Both are O(n) — different constants
def count_a(n):
total = 0
for i in range(n): # n ops
total += 1
for i in range(n): # n ops
total += 1
return total # T(n) = 2n => O(n)
def count_b(n):
total = 0
for i in range(5 * n): # 5n ops
total += 1
return total # T(n) = 5n => O(n)
print(count_a(10), count_b(10)) # 20 50Meilleurs, moyens et pires cas
La notation grand O décrit le pire cas ; Oméga décrit le meilleur cas ; Thêta est une borne serrée pour les deux. Lorsqu’un recruteur demande « la complexité », il parle presque toujours du pire cas.
def linear_search(nums, target):
for i, n in enumerate(nums):
if n == target:
return i # best case: target at index 0 => O(1)
return -1 # worst case: not found => O(n)
# Best case O(1): target is first element
print(linear_search([5,1,2,3], 5)) # 0
# Worst case O(n): target not in list
print(linear_search([1,2,3,4], 9)) # -1O(log n) : réduire de moitié l’espace de recherche
Un algorithme est en O(log n) lorsqu’il réduit l’entrée de moitié à chaque étape, comme dans la recherche binaire. Même pour un milliard d’éléments, cela ne représente qu’environ 30 étapes : c’est incroyablement rapide. Consultez le code.
def binary_search(arr, target):
lo, hi = 0, len(arr) - 1
steps = 0
while lo <= hi:
steps += 1
mid = (lo + hi) // 2
if arr[mid] == target:
return mid, steps
elif arr[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1, steps
import math
arr = list(range(1000))
idx, s = binary_search(arr, 999)
print(f'Found at {idx} in {s} steps (log2(1000)~={math.log2(1000):.1f})')O(n log n) : borne inférieure du tri
Tout tri par comparaison nécessite au moins O(n log n) dans le pire cas : c’est une véritable borne inférieure mathématique. Ainsi, trier puis parcourir les éléments donne une complexité globale de O(n log n), et non de O(n^2). Le code présente le tri fusion.
# Merge sort: O(n log n)
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(a, b):
res, i, j = [], 0, 0
while i < len(a) and j < len(b):
if a[i] <= b[j]: res.append(a[i]); i+=1
else: res.append(b[j]); j+=1
return res + a[i:] + b[j:]
print(merge_sort([5,2,8,1,9,3])) # [1,2,3,5,8,9]Complexité amortie
L’analyse amortie calcule le coût moyen sur de nombreuses opérations. En Python, append est en O(1) amorti : l’opération est généralement instantanée, tandis que le redimensionnement occasionnel en O(n) est réparti sur l’ensemble des opérations append.
# Dynamic array append is O(1) amortised
import sys
lst = []
capacities = []
for i in range(16):
lst.append(i)
capacities.append(sys.getsizeof(lst))
# Size jumps show reallocation events
for i, c in enumerate(capacities):
if i > 0 and capacities[i] != capacities[i-1]:
print(f'Realloc at i={i}, new size={c} bytes')Reconnaître la complexité dans le code
Règle rapide : comptez les boucles. Une boucle donne O(n), deux boucles imbriquées donnent O(n^2), et une boucle qui réduit de moitié donne O(log n). Les parcours indépendants add ; seules les boucles imbriquées multiply. Consultez le code.
# Two independent passes: O(n) + O(n) = O(n)
def two_passes(nums):
total = sum(nums) # O(n)
mean = total / len(nums)
diffs = [abs(n - mean) for n in nums] # O(n)
return max(diffs) # O(n)
# Overall: O(n) -- NOT O(n^2)
# Nested loops: O(n) * O(n) = O(n^2)
def all_pairs(nums):
pairs = []
for i in range(len(nums)): # O(n)
for j in range(i+1, len(nums)): # O(n)
pairs.append((nums[i], nums[j]))
return pairs # O(n^2)Bases de la complexité spatiale
La complexité spatiale suit la mémoire supplémentaire utilisée au-delà de l’entrée. Une inversion en place est en O(1) ; une table de hachage est en O(n). Lorsque vous échangez du temps contre de l’espace, indiquez toujours les deux.
# O(1) space: reverse in-place
def reverse_inplace(arr):
l, r = 0, len(arr) - 1
while l < r:
arr[l], arr[r] = arr[r], arr[l]
l += 1; r -= 1
# O(n) space: create reversed copy
def reverse_copy(arr):
return arr[::-1]
a = [1, 2, 3, 4, 5]
reverse_inplace(a)
print(a) # [5, 4, 3, 2, 1]Parler de complexité en entretien
Annoncez toujours la complexité sans attendre qu’on vous la demande : « Temps en O(n log n), espace en O(n). » Proposez ensuite une option plus rapide. Cette habitude témoigne d’une véritable expérience.
# Example of explaining complexity step by step
def two_sum(nums, target):
# O(n) time: one pass through nums
# O(n) space: hash map stores up to n elements
seen = {} # value -> index
for i, n in enumerate(nums):
complement = target - n
if complement in seen: # O(1) lookup
return [seen[complement], i]
seen[n] = i
return []
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]Vérification rapide
Vérification rapide — montrez ce que vous avez retenu de la notation grand O et des classes de complexité. Une question, vous en êtes capable. 🎯
Récapitulatif de la leçon
Récapitulatif : la notation grand O décrit la croissance dans le pire cas en supprimant les constantes ; vous connaissez les classes de O(1) à O(n!), et les boucles indépendantes s’additionnent tandis que les boucles imbriquées se multiplient.
Questions Fréquemment Posées
La leçon « La notation grand O depuis le début » est-elle gratuite ?
Oui — le texte complet de « La notation grand O depuis le début » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « La notation grand O depuis le début » ?
Comprenez pourquoi la croissance asymptotique est importante, comment éliminer les constantes et les termes d’ordre inférieur, et comment lire instantanément la notation grand O. Tu pratiques Coding Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « La notation grand O depuis le début » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Coding Interview Prep ?
Oui. Chaque leçon Coding Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- La notation grand O depuis le début
- Analyser les boucles et les boucles imbriquées
- Récursivité et méthode de l’arbre de récursion
- Complexité spatiale et compromis