Treci la conținutul principal

Împarte problema în două

O(log n) înseamnă timp logaritmic: fiecare pas taie în jumătate munca rămasă. Pentru că înjumătățirea micșorează numerele atât de repede, dublarea datelor de intrare adaugă doar un singur pas în plus.

16 elemente au nevoie de 4 înjumătățiri, 32 de elemente au nevoie de 5, un milion de elemente aproximativ 20, un miliard 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 ca să știe ce jumătate să arunce.


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ă de 4 ori, pentru că 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 încă un pas.

Prompt
Scrie un program Go care pornește cu 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: program Go și rezultatul capturat
Halving until one remains

Căutarea binară

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

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

Go oferă acest lucru și gata făcut: slices.BinarySearch() întoarce indexul și un bool. Când valoarea lipsește, indexul este poziția în care ar fi inserată.

Căutarea binară pas cu pas

Într-un slice sortat de 16 numere, căutarea lui 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 program Go care caută binar valoarea 13 în slice-ul sortat 1, 3, 5, 7, ... 31 (numerele impare, 16 elemente), folosind reperele lo și hi și numărând verificările. Când o găsește, afișează valoarea, indexul ei și numărul de verificări.
Ieșire: program Go și rezultatul capturat
Binary search step by step

Căutare binară cu pachetul slices

slices.BinarySearch() găsește 9 la indexul 4. Valoarea lipsă 10 dă found == false și indexul 5 — locul în care 10 s-ar potrivi ca slice-ul să rămână sortat.

Prompt
Scrie un program Go care folosește slices.BinarySearch pe slice-ul sortat 1, 3, 5, 7, 9, 11, 13, 15. Caută 9 și afișează indexul și indicatorul de găsire, apoi caută valoarea lipsă 10 și afișează-le din nou pe amândouă.
Ieșire: program Go și rezultatul capturat
Binary search with the slices package

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 Go rareori scrii singur o sortare — slices.Sort() este O(n log n). Să sortezi o dată, apoi să faci căutare binară de multe ori, este un tipar frecvent și rapid.

Sortează un slice

slices.Sort() ordonează cele 8 numere î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 rapid pe măsură ce slice-ul se mărește.

Prompt
Scrie un program Go care sortează slice-ul 31, 5, 17, 1, 23, 9, 27, 13 cu slices.Sort și afișează slice-ul sortat.
Ieșire: program Go și rezultatul capturat
Sort a slice