Ce înseamnă eficiența unui algoritm?
Imaginează-ți că vrei să găsești un cuvânt într-un dicționar cu 1.000.000 de cuvinte:
- 🐢 Verifici pagină cu pagină de la început → maxim 1.000.000 pași → O(n)
- 🚀 Cauți la mijloc, elimini jumătate (căutare binară) → maxim 20 pași → O(log n)
Pe 1 miliard de elemente: O(n) = 1 miliard de operații, O(log n) = doar 30. Eficiența contează enorm!
Analizăm două tipuri:
Numărul de operații elementare executate
Memoria suplimentară utilizată de algoritm
Notații asimptotice: O, Ω, Θ
Notațiile asimptotice descriu comportamentul unui algoritm pentru n → ∞, ignorând constantele și termenii de ordin inferior.
Limita superioară (worst case)
f(n) ≤ c · g(n) pentru n ≥ n₀
Limita inferioară (best case)
f(n) ≥ c · g(n) pentru n ≥ n₀
Limita exactă (tight bound)
c₁·g(n) ≤ f(n) ≤ c₂·g(n)
Reguli de simplificare
Clase de complexitate
| Clasă | n = 10 | n = 100 | n = 1000 | n = 10⁶ |
|---|---|---|---|---|
| O(1) | 1 | 1 | 1 | 1 |
| O(log n) | ~3 | ~7 | ~10 | ~20 |
| O(n) | 10 | 100 | 1 000 | 1 000 000 |
| O(n log n) | ~33 | ~664 | ~10 000 | ~2×10⁷ |
| O(n²) | 100 | 10 000 | 10⁶ | 10¹² |
| O(2ⁿ) | 1 024 | 10³⁰ | 10³⁰⁰ | ∞ |
📈 Grafic interactiv Big-O
Complexitate timp — exemple practice
O(1) — Acces la element în tablou
int x = v[5]; // O(1) — acces direct, indiferent de n int suma = a + b; // O(1) — operație aritmetică
O(n) — Parcurgere simplă
for (int i = 0; i < n; i++) { cout << v[i]; // executat de n ori → O(n) }
O(n²) — Bucle imbricate
for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) suma += v[i] * v[j]; // n × n = n² operații
O(log n) — Căutare binară
int cautareBinara(int v[], int n, int x) { int st = 0, dr = n - 1; while (st <= dr) { int mij = (st + dr) / 2; if (v[mij] == x) return mij; else if (v[mij] < x) st = mij + 1; else dr = mij - 1; } return -1; // la fiecare pas intervalul se înjumătățește → O(log n) }
Analiza corectă — cazuri speciale
// Două bucle SEPARATE (nu imbricate) → O(n) + O(n) = O(n) for (int i = 0; i < n; i++) suma1 += v[i]; for (int i = 0; i < n; i++) suma2 += v[i]; // Total: O(n), nu O(n²)
// Jumătate din n la fiecare pas → log₂n pași → O(log n) while (n > 1) n /= 2;
Complexitate spațiu
Complexitatea spațiu se referă la memoria suplimentară folosită de algoritm (nu se numără inputul în sine).
Algoritmul folosește doar câteva variabile auxiliare, indiferent de n
Exemplu: bubble sort in-placeSe alocă un tablou auxiliar de dimensiune n
Exemplu: merge sort (tablou temp)// O(1) spațiu — sortare prin selecție, in-place for (int i = 0; i < n-1; i++) { int minIdx = i; for (int j = i+1; j < n; j++) if (v[j] < v[minIdx]) minIdx = j; swap(v[i], v[minIdx]); // O(1) memorie extra }
// O(n) spațiu — copiere tablou int copie[100001]; for (int i = 0; i < n; i++) copie[i] = v[i]; // n elemente suplimentare
Algoritmi de sortare — comparație
| Algoritm | Best | Average | Worst | Spațiu | Stabil |
|---|---|---|---|---|---|
| Bubble Sort | O(n) | O(n²) | O(n²) | O(1) | ✅ |
| Selection Sort | O(n²) | O(n²) | O(n²) | O(1) | ❌ |
| Insertion Sort | O(n) | O(n²) | O(n²) | O(1) | ✅ |
| Merge Sort | O(n log n) | O(n log n) | O(n log n) | O(n) | ✅ |
| Quick Sort | O(n log n) | O(n log n) | O(n²) | O(log n) | ❌ |
| Heap Sort | O(n log n) | O(n log n) | O(n log n) | O(1) | ❌ |
| Counting Sort | O(n+k) | O(n+k) | O(n+k) | O(k) | ✅ |
📊 Comparație algoritmi de sortare
Bubble Sort — implementare C++
void bubbleSort(int v[], int n) { for (int i = 0; i < n-1; i++) { bool swap_facut = false; for (int j = 0; j < n-i-1; j++) { if (v[j] > v[j+1]) { swap(v[j], v[j+1]); swap_facut = true; } } if (!swap_facut) break; // optimizare: șirul deja sortat } // Complexitate: O(n²) worst/average, O(n) best }
Selection Sort — implementare C++
void selectionSort(int v[], int n) { for (int i = 0; i < n-1; i++) { int minIdx = i; for (int j = i+1; j < n; j++) if (v[j] < v[minIdx]) minIdx = j; if (minIdx != i) swap(v[i], v[minIdx]); } // Complexitate: O(n²) în toate cazurile }
Animație — Bubble Sort
Apasă Start pentru a vedea cum funcționează Bubble Sort pas cu pas. Barele de culoare portocalie sunt comparate, cele verzi sunt la locul final.
Probleme rezolvate — analiza complexității
5 exerciții cu analiza pas cu pas a complexității timp și spațiu.
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
s++;O(n · m)
💡 Explicație
Bucla externă rulează exact n iterații. Pentru fiecare, bucla internă rulează m iterații. Total = n × m operații elementare. Dacă n = m, e O(n²).
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++)
op();O(n²)
💡 Explicație
Numărul total de operații = 1 + 2 + 3 + ... + n = n(n+1)/2. În notație asimptotică ignoram constantele și termenii inferiori ⇒ O(n²).
i = n;
while (i > 0) {
for (j = 1; j <= n; j++) op();
i = i / 2;
}O(n log n)
💡 Explicație
Bucla while rulează log₂ n iterații (i se înjumătățește). Bucla for internă rulează n operații. Total = n · log n. Acesta este și complexitatea sortărilor optime (merge sort, heap sort, quicksort mediu).
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) {
c[i][j] = 0;
for (k = 1; k <= n; k++)
c[i][j] += a[i][k] * b[k][j];
}O(n³)
💡 Explicație
Trei bucle imbricate, fiecare cu n iterații ⇒ n × n × n = n³ operații. Pentru n = 1000 ⇒ 10⁹ operații — la limita timpului obișnuit de 1 s. Există algoritmi sub-cubici (Strassen O(n^2.81)), dar la BAC algoritmul clasic e ok.
T(n) = T(n/2) + O(1) T(1) = O(1)
O(log n)
💡 Explicație
Desfășurăm: T(n) = T(n/2) + c = T(n/4) + 2c = T(n/8) + 3c = ... = T(1) + c·log₂n = O(log n). Exemplu: cautareBinaraRec(v, st, dr, x) — la fiecare apel reduce intervalul la jumătate.
Comparație rapidă (Master Theorem): T(n) = 2T(n/2) + O(n) ⇒ O(n log n) (merge sort); T(n) = T(n−1) + O(1) ⇒ O(n) (factorial).
Probleme tip BAC — rezolvate
for(i=1; i<=n; i++) for(j=1; j<=i; j++) s = s + i*j;
i = n; while(i > 1) i = i / 2;
int freq[1001] = {0}; bool duplicat = false; for(int i = 0; i < n; i++) { freq[v[i]]++; if(freq[v[i]] > 1) { duplicat = true; break; } } // O(n) timp, O(k) spațiu unde k = domeniu valori
Referințe și resurse
UPB — Facultatea de Automatică
UniBuc — Facultatea de Matematică-Informatică
UBB Cluj — Informatică
TUIASI Iași — Calculatoare
pbinfo.ro — probleme BAC & olimpiadă
infoarena.ro — concursuri RO
LeetCode — pregătire interviuri IT
HackerRank — exerciții structurate
VisuAlgo — animații algoritmi
bigocheatsheet.com
cppreference.com — referință C++
Khan Academy