Treci la conținutul principal

Când munca se dublează

O(2ⁿ) înseamnă timp exponențial: un singur element în plus la intrare dublează munca. Aceasta este clasa de creștere la care algoritmii nu mai pot fi folosiți — nu doar pentru date de intrare uriașe, ci deja pentru unele medii.

Munca exponențială apare de obicei din recursivitatea care se ramifică: o funcție care se apelează pe ea însăși de două ori, iar fiecare dintre aceste apeluri se apelează din nou de două ori. Apelurile formează un arbore care se dublează la fiecare nivel.


Fibonacci recursiv

Șirul lui Fibonacci începe cu 0, 1, iar fiecare număr următor este suma celor două dinaintea lui: 0, 1, 1, 2, 3, 5, 8, 13, …

Definiția se transformă direct într-o funcție recursivă: fib(n) returnează fib(n-1) + fib(n-2). Este scurtă și corectă — dar exponențială, pentru că fiecare apel mai generează încă două, iar aceleași valori sunt calculate iar și iar. Doar fib(2) este recalculat de mii de ori într-un apel mai mare.

Fibonacci cu recursivitate

Un contor global numără fiecare apel. Calculul fib(10) = 55 necesită 177 de apeluri — pentru un singur număr mic. Arborele de apeluri se dublează la fiecare nivel.

Prompt
Scrie un program Python cu o funcție recursivă fib (fib de n este fib de n-1 plus fib de n-2, iar pentru n mai mic decât 2 se returnează n neschimbat) care incrementează un contor global de apeluri la fiecare apel. Calculează fib(10) și afișează rezultatul și numărul total de apeluri.
Ieșire: program Python complet
Fibonacci with recursion

De ce explodează

Urmăriți numărul de apeluri pe măsură ce n crește cu câte 5. El nu crește cu pași egali — se înmulțește. Fiecare +1 la n înseamnă aproximativ ×1,6 la apeluri; fiecare +5, mai mult de ×10.

La n = 50 numărul ar depăși 40 de miliarde de apeluri. Aceasta este capcana exponențială: codul pare inofensiv, iar testele mici se termină instantaneu.

Numărați apelurile pe măsură ce n crește

De la fib(5) la fib(25) intrarea crește de 5 ori — numărul de apeluri crește de peste 16 000 de ori, de la 15 la 242785.

Prompt
Scrie un program Python cu o funcție recursivă fib care își numără apelurile într-un contor global. Pentru n = 5, 10, 15, 20, 25 resetează contorul, rulează fib(n) și afișează câte o linie aliniată pentru fiecare n, cu numărul de apeluri, pentru a arăta creșterea exponențială.
Ieșire: program Python complet
Count the calls as n grows

Soluția: o buclă

Problema nu este Fibonacci — ci calcularea acelorași valori din nou și din nou. O buclă care urcă pornind de la 0 și 1, păstrând doar ultimele două valori, calculează fiecare număr exact o dată.

Asta înseamnă timp O(n) și spațiu O(1): 24 de pași în loc de 242785 de apeluri pentru fib(25). Același răspuns, o altă clasă de creștere — exact pentru asta există analiza algoritmilor.

Fibonacci cu o buclă

Două variabile urcă de-a lungul șirului; fiecare pas calculează un număr nou. fib(25) = 75025 în 24 de pași — versiunea recursivă avea nevoie de 242785 de apeluri pentru același răspuns.

Prompt
Scrie un program Python care calculează fib(25) cu o buclă în loc de recursivitate: păstrează ultimele două valori în două variabile și urcă pornind de la 0 și 1, numărând pașii buclei. Afișează rezultatul și numărul de pași.
Ieșire: program Python complet
Fibonacci with a loop