Treci la conținutul principal

Împarte problema în două

O(log n) înseamnă timp logaritmic: fiecare pas reduce la jumătate munca rămasă. Fiindcă înjumătățirea micșorează numerele atât de repede, dublarea intrării adaugă doar un pas în plus.

16 elemente au nevoie de 4 înjumătățiri, 32 de elemente de 5, un milion de elemente de aproximativ 20, un miliard de aproximativ 30. De aceea algoritmii logaritmici par instantanei chiar și pe date uriașe.

Exemplul clasic este căutarea binară — dar ea funcționează doar pe date sortate. Înjumătățirea are nevoie de o ordine pentru a ști care jumătate se aruncă.


O buclă care înjumătățește

Cel mai simplu mod de a vedea O(log n) este o buclă care împarte n la 2 până ajunge la 1. Numărul de runde este logaritmul lui n: pentru n = 16 bucla rulează 4 ori, deoarece 2 · 2 · 2 · 2 = 16.

Înjumătățire până rămâne unu

16 devine 8, 4, 2, 1 — patru pași. Dublarea lui n la 32 ar adăuga doar un pas în plus.

Prompt
Scrie un script PHP care pornește de la n = 16 și împarte n la 2 într-o buclă până ajunge la 1, afișând n după fiecare împărțire și numărând pașii. La final afișează câți pași au fost necesari.
Ieșire: script PHP
Halving until one remains

Căutare binară

Căutarea binară găsește o valoare într-un tablou sortat verificând mereu elementul din mijloc. Dacă mijlocul este prea mic, toată jumătatea din stânga este aruncată; dacă este prea mare, jumătatea din dreapta. Fiecare verificare înjumătățește intervalul de căutare.

Doi marcatori, $lo și $hi, țin intervalul curent. Bucla se termină când valoarea este găsită sau intervalul este gol.

PHP nu are o căutare binară gata făcută în biblioteca standard. Funcția integrată array_search() găsește o valoare parcurgând de la început — asta este liniar, O(n). Pe date sortate, o căutare binară scrisă de mână este unealta mai rapidă și îți poate spune și unde s-ar potrivi o valoare lipsă.

Căutarea binară pas cu pas

Într-un tablou sortat de 16 numere, căutarea valorii 13 are nevoie de doar 4 verificări: intervalul se micșorează 16 → 8 → 4 → 2 și ajunge la indexul 6. O căutare liniară ar fi avut nevoie aici de 7 pași — și de până la 16.

Prompt
Scrie un script PHP care face căutare binară în tabloul sortat 1, 3, 5, 7, ... 31 (numerele impare, 16 elemente) pentru valoarea 13, folosind marcatorii lo și hi și numărând verificările. Când valoarea este găsită, afișează valoarea, indexul ei și numărul de verificări.
Ieșire: script PHP
Binary search step by step

Căutare binară vs. array_search()

binarySearch() găsește 9 la indexul 4. Valoarea lipsă 10 dă găsit: false și indexul 5 — locul în care 10 s-ar potrivi pentru ca tabloul să rămână sortat. array_search() răspunde și ea, dar parcurge tabloul liniar, iar pentru valoarea lipsă 10 returnează doar false — fără poziție.

Prompt
Scrie o funcție PHP binarySearch care returnează indexul și un indicator „găsit” pentru o valoare din tabloul sortat 1, 3, 5, 7, 9, 11, 13, 15, unde indexul unei valori lipsă este poziția la care ar fi inserată. Caută 9 și valoarea lipsă 10 și afișează ambele rezultate, apoi rulează array_search pe aceleași două valori pentru comparație.
Ieșire: script PHP
Binary search vs array_search()

O(n log n): sortarea

O(n log n) se află între liniar și pătratic și este complexitatea algoritmilor buni de sortare: datele sunt înjumătățite iar și iar (log n niveluri), iar fiecare nivel face o cantitate liniară de muncă (n).

În PHP rar scrii singur o sortare — sort() este O(n log n). Ea primește tabloul prin referință și îl sortează pe loc: tabloul însuși este modificat, nu trebuie atribuit nimic înapoi. Sortarea o singură dată, apoi multe căutări binare, este un tipar frecvent și rapid.

Sortarea unui tablou

sort() ordonează cele 8 numere pe loc, în aproximativ 8 · log 8 = 24 pași — mult mai puțini decât cei 64 pe care i-ar folosi o sortare pătratică, iar diferența crește repede odată cu tabloul.

Prompt
Scrie un script PHP care sortează tabloul 31, 5, 17, 1, 23, 9, 27, 13 cu sort și afișează tabloul sortat.
Ieșire: script PHP
Sort an array