Scrivi un programma (o una funzione) che mostri quattro grandi complessità O time comuni a seconda di come viene eseguito. In qualsiasi forma assume un numero intero positivo N che si può presumere sia inferiore a 2 31 .
Quando il programma viene eseguito nella sua forma originale , dovrebbe avere una complessità costante . Cioè, la complessità dovrebbe essere Θ (1) o, equivalentemente, Θ (1 ^ N) .
Quando il programma viene invertito ed eseguito, dovrebbe avere una complessità lineare . Cioè, la complessità dovrebbe essere Θ (N) o, equivalentemente, Θ (N ^ 1) .
(Questo ha senso poichéN^1
è1^N
invertito.)Quando il programma viene raddoppiato , cioè concatenato a se stesso, ed eseguirlo dovrebbe avere esponenziale complessità, in particolare 2 N . Cioè, la complessità dovrebbe essere Θ (2 ^ N) .
(Questo ha senso dal momento che2
in2^N
è il doppio di1
in1^N
.)Quando il programma è raddoppiato e invertita ed eseguirlo dovrebbe avere polinomiale complessità, in particolare N 2 . Cioè, la complessità dovrebbe essere Θ (N ^ 2) .
(Questo ha senso poichéN^2
è2^N
invertito.)
Questi quattro casi sono gli unici che devi gestire.
Nota che per precisione sto usando la notazione big theta (Θ) invece della grande O perché i tempi di esecuzione dei tuoi programmi devono essere limitati sia sopra che sotto dalle complessità richieste. Altrimenti, scrivere una funzione in O (1) soddisferebbe tutti e quattro i punti. Non è troppo importante capire la sfumatura qui. Principalmente, se il tuo programma sta eseguendo operazioni k * f (N) per qualche costante k, è probabile che sia in Θ (f (N)).
Esempio
Se il programma originale fosse
ABCDE
quindi eseguirlo dovrebbe richiedere tempo costante. Cioè, se l'ingresso N è 1 o 2147483647 (2 31 -1) o qualsiasi valore in mezzo, dovrebbe terminare all'incirca nello stesso intervallo di tempo.
La versione inversa del programma
EDCBA
dovrebbe richiedere un tempo lineare in termini di N. Cioè, il tempo necessario per terminare dovrebbe essere approssimativamente proporzionale a N. Quindi N = 1 impiega il minor tempo e N = 2147483647 impiega di più.
La versione raddoppiata del programma
ABCDEABCDE
dovrebbe prendere tempo da due a-the-N in termini di N. Cioè, il tempo necessario per terminare dovrebbe essere approssimativamente proporzionale 2 N . Quindi se N = 1 termina in circa un secondo, N = 60 richiederebbe più tempo dell'età dell'universo per terminare. (No, non devi provarlo.)
La versione raddoppiata e invertita del programma
EDCBAEDCBA
dovrebbe richiedere un tempo quadrato in termini di N. Cioè, il tempo necessario per terminare dovrebbe essere approssimativamente proporzionale a N * N. Quindi se N = 1 termina in circa un secondo, N = 60 impiegherebbe circa un'ora per terminare.
Dettagli
Devi mostrare o sostenere che i tuoi programmi sono in esecuzione nelle complessità che dici di essere. Fornire alcuni dati sui tempi è una buona idea, ma cerca anche di spiegare perché teoricamente la complessità è corretta.
Va bene se in pratica i tempi dei tuoi programmi non sono perfettamente rappresentativi della loro complessità (o addirittura deterministici). ad esempio, l'ingresso N + 1 a volte potrebbe essere più veloce di N.
L'ambiente si sta eseguendo i programmi in fa materia. Puoi fare ipotesi di base su come le lingue popolari non perdano mai intenzionalmente tempo negli algoritmi ma, ad esempio, se conosci la tua versione particolare di Java implementa il bubble sort anziché un algoritmo di ordinamento più veloce , dovresti tenerne conto se esegui un ordinamento .
Per tutte le complessità qui ipotizziamo che stiamo parlando di scenari nel caso peggiore , non nel caso migliore o nel caso medio.
La complessità spaziale dei programmi non ha importanza, ma solo la complessità temporale.
I programmi possono produrre qualsiasi cosa. Importa solo che assumano un intero positivo N e abbiano la complessità temporale corretta.
Sono ammessi commenti e programmi multilinea. (Si può presumere che la versione
\r\n
inversa sia\r\n
per la compatibilità con Windows.)
Grandi promemoria
Dal più veloce al più lento è O(1), O(N), O(N^2), O(2^N)
(ordine 1, 2, 4, 3 sopra).
I termini più lenti dominano sempre, ad es O(2^N + N^2 + N) = O(2^N)
.
O(k*f(N)) = O(f(N))
per costante k. Quindi O(2) = O(30) = O(1)
e O(2*N) = O(0.1*N) = O(N)
.
Ricorda O(N^2) != O(N^3)
e O(2^N) != O(3^N)
.
Cheat sheet O grande e pulito.
punteggio
Questo è un normale codice golf. Vince il programma originale più breve (quello a tempo costante) in byte.
n = input(); for i in xrange(n): pass
ha una complessità esponenziale, perché prende delle 2 ** k
misure, dov'è k = log_2(n)
la dimensione dell'input. Dovresti chiarire se questo è il caso, poiché cambia drasticamente i requisiti.