📘 CodingMarble Learn

Complessità degli algoritmi: quanto cresce il lavoro?

Molti algoritmi risolvono lo stesso problema, ma alcuni richiedono molti più passi. Si misura un algoritmo contando i suoi passi di base al crescere della dimensione dell'input n, non con i secondi del cronometro. La notazione Big O dà un nome alla crescita: O(1) costante, O(log n) logaritmica, O(n) lineare, O(n log n) e O(n²) quadratica. La ricerca lineare è O(n), la ricerca binaria è O(log n); il bubble sort è O(n²), il merge sort è O(n log n). La memoria usata si chiama complessità spaziale.

🎬 Storia passo dopo passo

  1. Cerca il numero 13 in 16 scatole aprendole una per una. Ogni scatola aperta è un passo. Questa è la ricerca lineare: fino a n passi.
  2. Se le scatole sono in ordine, apri quella di mezzo e scarta la metà sbagliata. Ripeti. La ricerca binaria trova il 13 in soli 4 passi.
  3. Ora confronta cinque tipi di algoritmo quando n = 16. L'altezza della barra mostra il numero di passi. Alcune restano piccolissime, una è enorme.
  4. Raddoppia l'input da 8 a 16. O(n) raddoppia, O(n²) diventa quattro volte più grande e O(log n) cresce di appena 1.
  5. Ordinare 1000 elementi: il bubble sort fa circa un milione di confronti, il merge sort solo circa diecimila. La velocità di crescita conta soprattutto con input grandi.
  6. Tocca a te: muovi il cursore di n da 2 a 1024. Guarda quale barra schizza in alto più in fretta.

Suggerimento: trascina la scena 3D per ruotarla. Usa due dita per zoomare.

🤔 Dubbi comuni, chiariti

Perché non misurare semplicemente il programma con il cronometro?

Il tempo cambia da computer a computer. Il numero di passi no. Il passo 1 conta le scatole aperte, non i secondi.

Perché la ricerca binaria può saltare metà delle scatole?

Le scatole sono in ordine. Se quella di mezzo è più piccola del numero cercato, anche tutte quelle alla sua sinistra sono più piccole, quindi nessuna può essere la risposta. Guarda le scatole grigie nel passo 2.

Perché togliamo le costanti nella Big O?

La Big O riguarda la velocità con cui cresce il lavoro. 2n e n raddoppiano entrambi quando n raddoppia, quindi crescono allo stesso modo. Il passo 4 mostra il raddoppio.

O(n²) è sempre più lento di O(n log n)?

Per n piccolo può anche essere più veloce, ma quando n cresce, n² supera presto l'altro. Nel passo 5 con n = 1000 la differenza è di circa 100 volte.

Che cosa significa davvero log n qui?

log₂ n è quante volte puoi dimezzare n prima di arrivare a 1. Per 1024 è 10. Muovi il cursore nell'ultimo passo e guarda la barra blu crescere solo di 1 a ogni raddoppio di n.

Tanti algoritmi per un solo problema

Un algoritmo è una serie di passi precisi per risolvere un problema. La maggior parte dei problemi si può risolvere con più di un algoritmo. Per esempio, per trovare un nome in una lista puoi controllare ogni nome, oppure (se la lista è ordinata) puoi continuare a dimezzarla.

Entrambi danno la risposta giusta. La differenza è l'efficienza: quanto lavoro e quanta memoria servono. Un buon programmatore sceglie l'algoritmo che resta veloce anche quando i dati diventano tanti.

Confrontare gli algoritmi in base al tempo

Misurare con il cronometro non è giusto: un computer veloce fa sembrare buono un algoritmo lento. Perciò contiamo i passi di base (confronti, scambi, somme) in funzione della dimensione dell'input n.

Caso migliore, medio e peggiore

Il caso migliore è l'input più fortunato (il 13 è nella prima scatola: 1 passo). Il caso peggiore è il più sfortunato (il 13 non c'è: n passi). Di solito si indica il caso peggiore, perché è una garanzia: l'algoritmo non sarà mai più lento di così.

Complessità temporale e complessità spaziale

La complessità temporale dice come cresce il numero di passi con n. La complessità spaziale dice come cresce la memoria aggiuntiva con n. Il merge sort è veloce ma richiede memoria in più; il bubble sort quasi non ne richiede ma è lento.

La notazione Big O

La Big O descrive la velocità di crescita, ignorando i dettagli piccoli. Teniamo solo il termine più grande e togliamo i numeri costanti: 3n² + 5n + 2 diventa O(n²), perché per n grande la parte n² è quasi tutto.

Big ONomen = 16n = 1000Esempio
O(1)costante11leggere l'elemento 5 di un array
O(log n)logaritmica4circa 10ricerca binaria
O(n)lineare161000ricerca lineare, trovare il massimo
O(n log n)n log n64circa 10.000merge sort
O(n²)quadratica2561.000.000bubble sort, cicli annidati

Regola rapida per il codice: un ciclo su n elementi è O(n); un ciclo dentro un ciclo è O(n²); dimezzare il problema a ogni passo è O(log n).

Efficienza della ricerca lineare e binaria

La ricerca lineare controlla gli elementi uno per uno. Caso peggiore: n confronti, quindi O(n). Funziona su qualsiasi lista, ordinata o no.

La ricerca binaria richiede una lista ordinata. Guardi l'elemento di mezzo; se è troppo grande, scarti la metà destra, altrimenti la sinistra. Ogni passo dimezza la lista, quindi il caso peggiore è circa log₂ n + 1 confronti: O(log n). Per 1.000.000 di elementi sono circa 20 passi invece di 1.000.000.

Efficienza degli algoritmi di ordinamento

Bubble sort, insertion sort e selection sort usano un ciclo dentro un ciclo, quindi fanno circa n²/2 confronti: O(n²). L'insertion sort è O(n) nel caso migliore (una lista già ordinata).

Il merge sort dimezza la lista circa log₂ n volte e a ogni livello fa circa n lavoro: O(n log n). Richiede O(n) di memoria aggiuntiva.

La ricerca binaria richiede una lista ordinata. Se cerchi una sola volta, ordinare prima (n log n) costa più di una ricerca lineare (n). Se cerchi molte volte, ordinare una volta sola conviene.

Precondizioni, postcondizioni e trappole della ricorsione

Una precondizione è ciò che deve essere vero prima che l'algoritmo parta (ricerca binaria: la lista è ordinata). Una postcondizione è ciò che è garantito alla fine (ordinamento: ogni elemento è minore o uguale al successivo). Scriverle aiuta a testare e a dimostrare un algoritmo.

La ricorsione significa che una funzione richiama se stessa su un problema più piccolo. Errori comuni:

Provalo: gara tra due ricerche

Scrivi i numeri da 1 a 32 su foglietti di carta e mettili in ordine a faccia in giù. Chiedi a un amico di scegliere un numero segreto. Prima cerca uno per uno e conta i foglietti che giri. Poi cerca girando sempre il foglietto di mezzo. Ripeti 5 volte. Quale metodo non ha mai richiesto più di 6 mosse? Controlla con il cursore nell'ultimo passo 3D (n = 32: log₂ 32 = 5).

Formule e definizioni chiave

Esempi svolti

1. Una lista ha 50 nomi. Quanti confronti servono alla ricerca lineare nel caso migliore e nel peggiore?

Caso migliore: il nome è il primo → 1 confronto. Caso peggiore: il nome è l'ultimo o manca → 50 confronti. La ricerca lineare è O(n).

2. Qual è il massimo numero di confronti della ricerca binaria su una lista ordinata di 1024 elementi?

Ogni passo dimezza la lista: 1024 → 512 → 256 → 128 → 64 → 32 → 16 → 8 → 4 → 2 → 1. Sono 10 dimezzamenti, più l'ultimo controllo: al massimo 11 confronti (log₂ 1024 = 10).

3. Trova la Big O di f(n) = 4n² + 10n + 7.

Tieni il termine più grande (4n²) e togli la costante 4: O(n²).

4. Un ciclo fa variare i da 1 a n, e dentro di esso un altro ciclo fa variare j da 1 a n. Quante volte viene eseguita l'istruzione interna?

n volte per ciascuno degli n valori di i: n × n = n². Complessità temporale O(n²).

5. Un programma O(n²) ordina 1000 elementi in 2 secondi. Circa quanto tempo serve per 3000 elementi?

n diventa 3 volte più grande, quindi n² diventa 3² = 9 volte più grande: circa 2 × 9 = 18 secondi.

6. Confronta bubble sort e merge sort per n = 1000 elementi.

Bubble sort: circa n²/2 = 500.000 confronti. Merge sort: circa n log₂ n = 1000 × 10 = 10.000. Il merge sort fa circa 50 volte meno lavoro, ma richiede memoria in più.

Errori comuni

Quiz di allenamento

1. Qual è la complessità temporale nel caso peggiore della ricerca lineare?
2. La ricerca binaria funziona solo se la lista è:
3. Se n raddoppia, un algoritmo O(n²) impiega circa:
4. Quale ordinamento è O(n log n)?
5. La Big O di 7n + 300 è:

Esercizi: rispondi da solo

Scrivi o scegli la risposta, poi premi Controlla. Usa un suggerimento se sei bloccato; la soluzione completa appare dopo la tua risposta.

Domande frequenti

Che cos'è la complessità temporale in parole semplici?

Dice come cresce il numero di passi di un algoritmo quando l'input diventa più grande. Per esempio O(n) significa che se raddoppi l'input, raddoppiano i passi.

Qual è la differenza tra complessità temporale e spaziale?

La complessità temporale misura i passi; quella spaziale misura la memoria aggiuntiva. Un algoritmo può essere veloce ma usare molta memoria, come il merge sort.

Qual è la Big O più veloce?

O(1) (costante) è la migliore, poi O(log n), O(n), O(n log n), O(n²), e l'esponenziale O(2ⁿ) è la peggiore tra quelle più comuni.

Dove si studia

Canada (Ontario)Grade 12C. Designing Modular Programs
Ukraine11 класAlgorithms
England (GCSE, A level)Year 103.1 Fundamentals of algorithms
USA (Common Core, NGSS, AP)Grade 11Selection and Iteration
USA (Common Core, NGSS, AP)Grade 11Algorithms and Programming
South Korea고등학교 2학년Algorithms and programming
South Korea고등학교 3학년Abstraction and algorithms

Da studiare prima

Da studiare dopo