Cosa significa esattamente O (log n)?


2139

Sto imparando i tempi di esecuzione di Big O Notation e i tempi ammortizzati. Capisco la nozione di O (n) tempo lineare, nel senso che la dimensione dell'ingresso influenza la crescita dell'algoritmo in modo proporzionale ... e lo stesso vale, ad esempio, per il tempo quadratico O (n 2 ) ecc. Anche algoritmi , come i generatori di permutazione, con tempi O (n!) , che crescono per fattoriali.

Ad esempio, la seguente funzione è O (n) perché l'algoritmo cresce in proporzione al suo input n :

f(int n) {
  int i;
  for (i = 0; i < n; ++i)
    printf("%d", i);
}

Allo stesso modo, se ci fosse un ciclo nidificato, il tempo sarebbe O (n 2 ).

Ma cos'è esattamente O (log n) ? Ad esempio, cosa significa che l'altezza di un albero binario completo è O (log n) ?

So (forse non in grande dettaglio) che cos'è il logaritmo, nel senso che: log 10 100 = 2, ma non riesco a capire come identificare una funzione con un tempo logaritmico.


61
Un albero binario a 1 nodo ha altezza log2 (1) +1 = 1, un albero a 2 nodi ha altezza log2 (2) +1 = 2, un albero a 4 nodi ha altezza log2 (4) +1 = 3 e presto. Un albero n-node ha altezza log2 (n) +1, quindi l'aggiunta di nodi all'albero fa sì che la sua altezza media cresca logaritmicamente.
David R Tribble,

36
Una cosa che vedo nella maggior parte delle risposte è che essenzialmente descrivono "O (qualcosa)" significa che il tempo di esecuzione dell'algoritmo cresce in proporzione a "qualcosa". Dato che hai chiesto "significato esatto" di "O (log n)", non è vero. Questa è la descrizione intuitiva della notazione di Big-Theta, non di Big-O. O (log n) significa intuitivamente il tempo di esecuzione cresce al massimo proporzionale alla "log n": stackoverflow.com/questions/471199/...
Mehrdad Afshari

31
Ricordo sempre di dividere e conquistare come esempio per O (log n)
RichardOD,

14
È importante rendersi conto che il suo log base 2 (non base 10). Questo perché ad ogni passaggio di un algoritmo, rimuovi metà delle tue scelte rimanenti. Nell'informatica abbiamo quasi sempre a che fare con log base 2 perché possiamo ignorare le costanti. Tuttavia ci sono alcune eccezioni (ovvero i tempi di esecuzione di Quad Tree sono log base 4)
Ethan,

13
@Ethan: non importa in quale base ti trovi, poiché la conversione di base è solo una moltiplicazione costante, la formula è log_b (x) = log_d (x) / log_d (b). Log_d (b) sarà solo una costante.
mindvirus,

Risposte:


2711

Non riesco a capire come identificare una funzione con un tempo di registro.

Gli attributi più comuni della funzione logaritmica del tempo di esecuzione sono:

  • la scelta del prossimo elemento su cui eseguire alcune azioni è una delle diverse possibilità, e
  • solo uno dovrà essere scelto.

o

  • gli elementi su cui viene eseguita l'azione sono cifre di n

Ecco perché, ad esempio, cercare le persone in una rubrica è O (registro n). Non è necessario controllare ogni persona nell'elenco telefonico per trovare quella giusta; invece, puoi semplicemente dividere e conquistare guardando in base a dove il loro nome è in ordine alfabetico, e in ogni sezione devi solo esplorare un sottoinsieme di ogni sezione prima di trovare il numero di telefono di qualcuno.

Ovviamente, una rubrica più grande ti impiegherà ancora più tempo, ma non crescerà rapidamente come l'aumento proporzionale delle dimensioni aggiuntive.


È possibile espandere l'esempio della rubrica per confrontare altri tipi di operazioni e il loro tempo di esecuzione. Supporremo che la nostra rubrica abbia attività commerciali (le "Pagine gialle") che hanno nomi e persone univoci (le "Pagine bianche") che potrebbero non avere nomi univoci. Un numero di telefono è assegnato al massimo a una persona o azienda. Supporremo anche che ci vuole tempo costante per passare a una pagina specifica.

Ecco i tempi di esecuzione di alcune operazioni che potremmo eseguire sulla rubrica, dal più veloce al più lento:

  • O (1) (nel peggiore dei casi): data la pagina in cui si trova il nome di un'azienda e il nome dell'azienda, trova il numero di telefono.

  • O (1) (nel caso medio): data la pagina in cui si trova il nome di una persona e il suo nome, trova il numero di telefono.

  • O (registro n): dato il nome di una persona, trova il numero di telefono selezionando un punto casuale a metà della parte del libro che non hai ancora cercato, quindi controlla se il nome della persona è a quel punto. Quindi ripetere il processo a metà strada attraverso la parte del libro in cui si trova il nome della persona. (Questa è una ricerca binaria per il nome di una persona.)

  • O (n): trova tutte le persone i cui numeri di telefono contengono la cifra "5".

  • O (n): dato un numero di telefono, trova la persona o l'azienda con quel numero.

  • O (n registro n): c'è stato un errore nell'ufficio della stampante e la nostra rubrica telefonica ha inserito tutte le sue pagine in ordine casuale. Correggi l'ordinamento in modo che sia corretto guardando il nome su ogni pagina e poi posizionando quella pagina nel punto appropriato in una nuova rubrica vuota.

Per gli esempi seguenti, ora siamo nell'ufficio della stampante. Le rubriche telefoniche sono in attesa di essere spedite a ciascun residente o azienda e su ogni rubrica telefonica è presente un adesivo che identifica dove deve essere spedita. Ogni persona o azienda riceve una rubrica.

  • O (n log n): Vogliamo personalizzare la rubrica, quindi troveremo il nome di ogni persona o azienda nella loro copia designata, quindi cercheremo il loro nome nel libro e scrivere una breve nota di ringraziamento per il loro patrocinio .

  • O (n 2 ): si è verificato un errore in ufficio e ogni voce in ciascuna rubrica ha un ulteriore "0" alla fine del numero di telefono. Prendi un po 'di bianco e rimuovi ogni zero.

  • O (n · n!): Siamo pronti per caricare le rubriche nel dock di spedizione. Sfortunatamente, il robot che avrebbe dovuto caricare i libri è andato in tilt: sta mettendo i libri sul camion in un ordine casuale! Ancora peggio, carica tutti i libri sul camion, quindi controlla se sono nell'ordine giusto e, in caso contrario, li scarica e ricomincia. (Questo è il temuto bogo sort .)

  • O (n n ): ripari il robot in modo che carichi correttamente le cose. Il giorno successivo, uno dei tuoi colleghi ti fa uno scherzo e collega il robot della banchina di carico ai sistemi di stampa automatizzati. Ogni volta che il robot carica un libro originale, la stampante di fabbrica esegue una duplicazione di tutte le rubriche! Fortunatamente, i sistemi di rilevamento dei bug del robot sono abbastanza sofisticati che il robot non prova a stampare ancora più copie quando incontra un libro duplicato per il caricamento, ma deve comunque caricare tutti i libri originali e duplicati che sono stati stampati.


81
@cletus: Per coincidenza, temo. L'ho scelto perché le rubriche hanno una N grande, le persone capiscono cosa sono e cosa fanno e perché è versatile come esempio. Inoltre devo usare i robot nella mia spiegazione! Una vittoria a tutto tondo. (Inoltre, sembra che la tua risposta sia stata fatta prima ancora che io fossi un membro di StackOverflow!)
John Feminella,

12
"Si è verificato un errore in ufficio e ogni voce in ciascuna rubrica ha un ulteriore" 0 "alla fine del numero di telefono. Prendi un po 'di bianco e rimuovi ogni zero." <- questo non è ordine N al quadrato. N è definito come la dimensione dell'input. La dimensione dell'input è il numero di numeri di telefono, che è il numero di numeri per libro moltiplicato per il numero di libri. Questa è ancora un'operazione di tempo lineare.
Billy ONeal,

21
@Billy: in questo esempio, Nè il numero di persone in un singolo libro. Poiché ogni persona nella rubrica riceve anche la propria copia del libro, ci sono rubriche N identiche , ognuna con le Npersone, che è O (N ^ 2).
John Feminella,

48
O (1) non è il caso migliore, piuttosto che il caso peggiore in quanto è stranamente evidenziato come?
Svip,

54
Mi ci è voluto del tempo O (long⅝n! N-55/2) per trovare una definizione O (log n) che alla fine abbia senso. +1
iAteABug_And_iLiked_it

611

O(log N)fondamentalmente significa che il tempo sale in modo lineare mentre nsale in modo esponenziale. Quindi, se ci vogliono 1secondi per calcolare gli 10elementi, ci vorranno 2secondi per calcolare gli 100elementi, 3secondi per calcolare gli 1000elementi e così via.

È O(log n)quando dividiamo e conquistiamo il tipo di algoritmi, ad esempio la ricerca binaria. Un altro esempio è l'ordinamento rapido in cui ogni volta che dividiamo l'array in due parti e ogni volta ci vuole O(N)tempo per trovare un elemento pivot. Quindi N O(log N)


108
Tre linee di saggezza che battono tutte le altre risposte al saggio ... :) Nel caso in cui a qualcuno manchi, nel contesto di programmazione, la base del registro è 2 (non 10), quindi O (registro n) scala come 1 secondo per 10 elementi, 2 secondi per 20, 3 per 40 ecc.
nawfal

3
Concordato, conciso e chiaro, anche se la domanda finale dell'OP era come identificare una funzione logaritmica, non proprio "che cos'è"
Adam

4
sì, la funzione logaritmica è inversa alla funzione esponenziale. ((log x) base a) è inverso di (a power x). L'analisi qualitativa di queste funzioni con grafici darebbe più intuizione.
scambio eccessivo

7
Mi ci sono voluti circa 3 read-through per rendermi conto che non era sbagliato. Il tempo passa linearmente, mentre il numero di elementi è esponenziale. Ciò significa più elementi in meno tempo . Questo è un problema per coloro che visualizzano logcome una curva di registro familiare su un grafico.
Qix - MONICA È STATA MISTREATA il

1
Penso che questa sia un'ottima risposta, fatta eccezione per la parte in cui afferma che la ricerca binaria è un algoritmo di divisione e conquista. Non lo è.
code_dredd,

579

Molte buone risposte sono già state inviate a questa domanda, ma credo che ci manchi davvero una importante, vale a dire la risposta illustrata.

Cosa significa dire che l'altezza di un albero binario completo è O (log n)?

Il seguente disegno raffigura un albero binario. Nota come ogni livello contiene il doppio del numero di nodi rispetto al livello sopra (quindi binario ):

Albero binario

La ricerca binaria è un esempio con complessità O(log n). Diciamo che i nodi nel livello inferiore dell'albero nella figura 1 rappresentano elementi in una raccolta ordinata. La ricerca binaria è un algoritmo di divisione e conquista e il disegno mostra come avremo bisogno (al massimo) di 4 confronti per trovare il record che stiamo cercando in questo set di dati di 16 elementi.

Supponiamo di avere invece un set di dati con 32 elementi. Continua il disegno sopra per scoprire che ora avremo bisogno di 5 confronti per trovare quello che stiamo cercando, poiché l'albero è cresciuto di un livello più in profondità quando abbiamo moltiplicato la quantità di dati. Di conseguenza, la complessità dell'algoritmo può essere descritta come un ordine logaritmico.

Tracciando log(n)su un semplice foglio di carta, si otterrà un grafico in cui l'aumento della curva decelera nall'aumentare:

O (registro n)


60
"Nota come ogni livello contiene il doppio numero di nodi rispetto al livello sopra (quindi binario)" Questo non è corretto. Quello che stai descrivendo è un albero binario bilanciato . Un albero binario significa solo che ogni nodo ha al massimo due figli.
Oenotria,

8
In realtà, è un albero binario bilanciato molto speciale, chiamato albero binario completo. Ho modificato la risposta ma ho bisogno di qualcuno che la approvi.
user21820

5
Un albero binario completo non deve avere l'ultimo livello da riempire completamente. Direi che un "albero binario completo" è più appropriato.
Mr. AJ,

La tua risposta cerca di rispondere in modo più concreto al problema originale del PO, quindi è migliore dell'attuale risposta accettata (IMO), ma è ancora molto incompleta: fai solo un mezzo esempio e 2 immagini ...
nbro

2
Questo albero contiene 31 elementi, non 16. Perché viene chiamato un set di dati di 16 elementi? Ogni nodo su di esso rappresenta un numero, altrimenti sarebbe un albero binario inefficiente: P
Perry Monschau,

245

La spiegazione seguente sta usando il caso di un bilanciamento completo albero binario per aiutarti a capire come otteniamo la complessità del tempo logaritmico.

L'albero binario è un caso in cui un problema di dimensione n è diviso in sotto-problema di dimensione n / 2 fino a quando non si raggiunge un problema di dimensione 1:

altezza di un albero binario

Ed è così che ottieni O (log n) che è la quantità di lavoro che deve essere fatto sull'albero sopra per raggiungere una soluzione.

Un algoritmo comune con O (log n) complessità temporale è Ricerca binaria la cui relazione ricorsiva è T (n / 2) + O (1) cioè ad ogni livello successivo dell'albero dividi il problema a metà e fai costante lavoro aggiuntivo.


2
novizio qui. Quindi potresti dire che l'altezza dell'albero è il tasso di divisione per ricorsione per raggiungere la dimensione n = 1?
Cody,

@Cody, sì, per la maggior parte la tua osservazione è accurata. Questo esempio illustra / utilizza log_2. La tua osservazione andrebbe oltre log_2e sarebbe precisa per ogni log_xdove x > 1. Fare una divisione diretta potrebbe non portare esattamente a 1, quindi potresti voler dire la divisione ricorsiva fino a quando Ceiling()l'ultima divisione è uguale a 1 o qualcosa di simile.
James Oravec,

199

Panoramica

Altri hanno fornito buoni esempi di diagrammi, come i diagrammi ad albero. Non ho visto alcun semplice esempio di codice. Quindi, oltre alla mia spiegazione, fornirò alcuni algoritmi con semplici istruzioni di stampa per illustrare la complessità delle diverse categorie di algoritmi.

Innanzitutto, vorrai avere un'idea generale del logaritmo, che puoi ottenere da https://en.wikipedia.org/wiki/Logarithm . Uso delle scienze naturali ee registro naturale. I discepoli di ingegneria useranno log_10 (log base 10) e gli informatici useranno molto log_2 (log base 2), poiché i computer sono basati su binari. A volte vedrai abbreviazioni di log naturale come ln(), gli ingegneri normalmente lasciano spento _10 e usano solo log()e log_2 è abbreviato come lg(). Tutti i tipi di logaritmi crescono in modo simile, per questo condividono la stessa categoria di log(n).

Quando guardi gli esempi di codice qui sotto, ti consiglio di guardare O (1), quindi O (n), quindi O (n ^ 2). Dopo che sei bravo con quelli, allora guarda gli altri. Ho incluso esempi chiari e varianti per dimostrare come i cambiamenti sottili possano comunque portare alla stessa categorizzazione.

Puoi pensare a O (1), O (n), O (logn), ecc. Come classi o categorie di crescita. Alcune categorie richiedono più tempo rispetto ad altre. Queste categorie ci aiutano a ordinare le prestazioni dell'algoritmo. Alcuni sono cresciuti più velocemente man mano che l'input n cresce. La tabella seguente mostra numericamente tale crescita. Nella tabella seguente pensa a log (n) come al soffitto di log_2.

inserisci qui la descrizione dell'immagine

Esempi di codice semplice di varie grandi categorie O:

O (1) - Esempi di tempo costante:

  • Algoritmo 1:

L'algoritmo 1 stampa ciao una volta e non dipende da n, quindi verrà sempre eseguito a tempo costante, quindi lo è O(1).

print "hello";
  • Algoritmo 2:

Algorithm 2 stampa ciao 3 volte, tuttavia non dipende da una dimensione di input. Anche se n cresce, questo algoritmo stampa sempre ciao solo 3 volte. Detto questo, è una costante, quindi anche questo algoritmo O(1).

print "hello";
print "hello";
print "hello";

O (log (n)) - Esempi logaritmici:

  • Algoritmo 3 - Funziona come "log_2"

L'algoritmo 3 mostra un algoritmo che viene eseguito in log_2 (n). Notare che l'operazione post del ciclo for moltiplica il valore corrente di i per 2, quindi iva da 1 a 2 a 4 a 8 a 16 a 32 ...

for(int i = 1; i <= n; i = i * 2)
  print "hello";
  • Algoritmo 4 - Funziona come "log_3"

L'algoritmo 4 mostra log_3. L'avviso iva da 1 a 3 a 9 a 27 ...

for(int i = 1; i <= n; i = i * 3)
  print "hello";
  • Algoritmo 5 - Funziona come "log_1.02"

L'algoritmo 5 è importante, poiché aiuta a dimostrare che fintanto che il numero è maggiore di 1 e il risultato viene ripetutamente moltiplicato contro se stesso, si sta osservando un algoritmo logaritmico.

for(double i = 1; i < n; i = i * 1.02)
  print "hello";

O (n) - Esempi di tempo lineare:

  • Algoritmo 6

Questo algoritmo è semplice, che stampa ciao n volte.

for(int i = 0; i < n; i++)
  print "hello";
  • Algoritmo 7

Questo algoritmo mostra una variazione, dove stampa ciao n / 2 volte. n / 2 = 1/2 * n. Ignoriamo la costante 1/2 e vediamo che questo algoritmo è O (n).

for(int i = 0; i < n; i = i + 2)
  print "hello";

O (n * log (n)) - nlog (n) Esempi:

  • Algoritmo 8

Pensa a questo come una combinazione di O(log(n))e O(n). La nidificazione dei cicli for ci aiuta a ottenere ilO(n*log(n))

for(int i = 0; i < n; i++)
  for(int j = 1; j < n; j = j * 2)
    print "hello";
  • Algoritmo 9

L'algoritmo 9 è come l'algoritmo 8, ma ciascuno dei loop ha consentito variazioni, il che risulta comunque nel risultato finale O(n*log(n))

for(int i = 0; i < n; i = i + 2)
  for(int j = 1; j < n; j = j * 3)
    print "hello";

O (n ^ 2) - n quadrati Esempi:

  • Algoritmo 10

O(n^2) si ottiene facilmente annidando lo standard per i loop.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j++)
    print "hello";
  • Algoritmo 11

Come l'algoritmo 10, ma con alcune variazioni.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j = j + 2)
    print "hello";

O (n ^ 3) - n cubi Esempi:

  • Algoritmo 12

Questo è come l'algoritmo 10, ma con 3 loop anziché 2.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j++)
    for(int k = 0; k < n; k++)
      print "hello";
  • Algoritmo 13

Come l'algoritmo 12, ma con alcune variazioni che ancora producono O(n^3).

for(int i = 0; i < n; i++)
  for(int j = 0; j < n + 5; j = j + 2)
    for(int k = 0; k < n; k = k + 3)
      print "hello";

Sommario

Quanto sopra fornisce diversi esempi diretti e variazioni per aiutare a dimostrare quali sottili cambiamenti possono essere introdotti che non cambiano davvero l'analisi. Spero che ti dia abbastanza informazioni.


17
Eccezionale. La migliore spiegazione per me che abbia mai visto. Sarebbe più bello se O(n^2)si nota come una combinazione di O(n)e O(n), quindi O(n) * O(n) = O(n * n) = O(n^2). Sembra un po 'di saltare senza questa equazione. Questa è la ripetizione della spiegazione precedente, ma penso che questa ripetizione possa fornire maggiore sicurezza ai lettori per la comprensione.
Eonil,

2
Questa è semplicemente la migliore spiegazione di sempre.
Edgar Kiljak,

2
@IceTea, per darti un'idea / intuizione della tua domanda. Se tracciati un grafico ncontro n/2vedrai che entrambi fanno una linea retta. Questo li colloca nella stessa classe in quanto hanno tassi di crescita simili (pensatelo come la forma del grafico). Allo stesso modo, se hai tracciato un grafico log_2contro log_3vedrai che entrambi assumono "forme simili" o "tassi di crescita simili".
James Oravec,

1
@IceTea, la spiegazione fornita da @Shai e @James è più accurata, n/2 or 2n or n+2 or navrà una linea diversa nel grafico ma avrà lo stesso tasso di crescita, il che significa che tutti seguiranno una crescita lineare.
Naresh Joshi il

2
Che ne dici del caso in cui abbiamo due loop nidificati, ma il secondo iteratore dipende dal primo, questa dipendenza influisce sulla complessità temporale?
Bionix1441

131

Se avessi una funzione che accetta:

1 millisecond to complete if you have 2 elements.
2 milliseconds to complete if you have 4 elements.
3 milliseconds to complete if you have 8 elements.
4 milliseconds to complete if you have 16 elements.
...
n milliseconds to complete if you have 2^n elements.

Quindi ci vuole il log 2 (n) tempo. La notazione Big O , parlando in senso lato, significa che la relazione deve essere vera solo per n grande, e che fattori costanti e termini più piccoli possono essere ignorati.


log2 (n) è uguale a o (log n)?
Sven van den Boogaart,

Sì, vedi il commento di nawfal per un'altra risposta qui: (copia-incolla) - nel contesto di programmazione, la base del registro è 2 (non 10), quindi O (registro n) scala come 1 secondo per 10 elementi, 2 secondo per 20 , 3 per 40 ecc.
Andrejs

@SvenvandenBoogaart, l'esempio in questa soluzione illustra log_2, che è nella classe O(log(n)). Ce ne sono molti altri nella stessa classe, O(log(n))ovvero log_xdovex > 1
James Oravec,

@Andrejs, il tuo commento so O(log n) scales like 1 sec for 10 elements, 2 sec for 20, 3 for 40 etcè impreciso. Quel modello / classe corrisponderebbe / allineare con O(n)non O(log(n)). Se qualcuno fosse interessato, log_10un esempio equivalente sarebbe 1 secondo per 10 elementi, 2 secondi per 100, 3 per 1000, ecc.
James Oravec

99

Il tempo di esecuzione logaritmico ( O(log n)) significa essenzialmente che il tempo di esecuzione aumenta in proporzione al logaritmo della dimensione di input, ad esempio se 10 elementi impiegano al massimo un certo periodo di tempo xe 100 elementi impiegano al massimo, diciamo 2x, e 10.000 elementi prende al massimo 4x, quindi sembra una O(log n)complessità temporale.


1
+1, ma dovresti davvero sottolineare che è log2, non log10.
Adriano Varoli Piazza

62
log2 o log10 è irrilevante. Differiscono solo per un fattore di scala, che li rende dello stesso ordine, cioè crescono ancora allo stesso ritmo.
Noldorin,

17
La cosa divertente dei logaritmi è che quando si confrontano le altezze relative, la base esatta che usi non ha importanza. log 10,000 / log 100è 2 indipendentemente dalla base utilizzata.
Anon.

12
Per essere nitido, O (lg n) significa che l'autonomia è al massimo proporzionale a lg n. Quello che descrivi è Theta (lg n).

1
@rgrig: è vero. Ho modificato alcuni "at mosts" per indicare la natura del limite superiore del big-O.
Anon.

95

Il logaritmo

Ok proviamo a comprendere appieno cos'è un logaritmo.

Immagina di avere una corda e l'abbiamo legata a un cavallo. Se la corda è direttamente legata al cavallo, la forza che il cavallo dovrebbe estrarre (diciamo, da un uomo) è direttamente 1.

Ora immagina che la corda sia attorcigliata attorno a un palo. Ora il cavallo per fuggire dovrà tirare più volte più forte. La quantità di volte dipenderà dalla rugosità della corda e dalle dimensioni del palo, ma supponiamo che moltiplicherà la forza di 10 (quando la corda fa un giro completo).

Ora, se la corda viene avvolta una volta, il cavallo dovrà tirare 10 volte più forte. Se l'umano decide di renderlo davvero difficile per il cavallo, può avvolgere di nuovo la corda attorno a un palo, aumentandone la forza di altre 10 volte. Un terzo loop aumenterà di nuovo la forza di altre 10 volte.

inserisci qui la descrizione dell'immagine

Possiamo vedere che per ogni ciclo, il valore aumenta di 10. Il numero di turni necessari per ottenere qualsiasi numero è chiamato logaritmo del numero, cioè abbiamo bisogno di 3 post per moltiplicare la tua forza di 1000 volte, 6 post per moltiplicare la tua forza di 1.000.000.

3 è il logaritmo di 1.000 e 6 è il logaritmo di 1.000.000 (base 10).

Cosa significa effettivamente O (log n)?

Nel nostro esempio sopra, il nostro "tasso di crescita" è O (log n) . Per ogni anello aggiuntivo, la forza che la nostra corda è in grado di gestire è 10 volte di più:

Turns | Max Force
  0   |   1
  1   |   10
  2   |   100
  3   |   1000
  4   |   10000
  n   |   10^n

Ora l'esempio sopra ha usato la base 10, ma fortunatamente la base del registro è insignificante quando parliamo di notazione grande.

Ora immaginiamo che tu stia provando a indovinare un numero tra 1-100.

Your Friend: Guess my number between 1-100! 
Your Guess: 50
Your Friend: Lower!
Your Guess: 25
Your Friend: Lower!
Your Guess: 13
Your Friend: Higher!
Your Guess: 19
Your Friend: Higher!
Your Friend: 22
Your Guess: Lower!
Your Guess: 20
Your Friend: Higher!
Your Guess: 21
Your Friend: YOU GOT IT!  

Ora ci sono volute 7 ipotesi per farlo bene. Ma qual è la relazione qui? Qual è il maggior numero di elementi che puoi indovinare da ogni ipotesi aggiuntiva?

Guesses | Items
  1     |   2
  2     |   4
  3     |   8
  4     |   16
  5     |   32
  6     |   64
  7     |   128
  10    |   1024

Usando il grafico, possiamo vedere che se utilizziamo una ricerca binaria per indovinare un numero compreso tra 1 e 100 ci impiegheranno al massimo 7 tentativi. Se avessimo 128 numeri, potremmo anche indovinare il numero in 7 tentativi, ma 129 numeri ci porteranno al massimo 8 tentativi (in relazione ai logaritmi, qui avremmo bisogno di 7 ipotesi per un intervallo di 128 valori, 10 ipotesi per un intervallo di 1024 valori 7 è il logaritmo di 128, 10 è il logaritmo di 1024 (base 2)).

Nota che ho osato "al massimo". La notazione Big-O si riferisce sempre al caso peggiore. Se sei fortunato, puoi indovinare il numero in un tentativo e quindi il caso migliore è O (1), ma questa è un'altra storia.

Possiamo vedere che per ogni ipotesi il nostro set di dati si sta riducendo. Una buona regola empirica per identificare se un algoritmo ha un tempo logaritmico è vedere se il set di dati si restringe di un certo ordine dopo ogni iterazione

Che dire di O (n log n)?

Alla fine vi imbatterete in un algoritmo O (n log (n)) di tempo linearitmico . La regola empirica sopra si applica nuovamente, ma questa volta la funzione logaritmica deve essere eseguita n volte, ad esempio riducendo la dimensione di un elenco n volte , che si verifica in algoritmi come un mergesort.

È possibile identificare facilmente se il tempo algoritmico è n log n. Cerca un ciclo esterno che scorre attraverso un elenco (O (n)). Quindi cerca di vedere se esiste un anello interno. Se il loop interno sta tagliando / riducendo il set di dati su ciascuna iterazione, quel loop è (O (log n)), e quindi l'algoritmo complessivo è = O (n log n) .

Disclaimer: l'esempio del logaritmo delle corde è stato preso dall'eccellente libro Mathematician's Delight di W.Sawyer .


No. In our example above, our 'growth rate' is O(log n). For every additional loop, the force our rope can handle is 10 times more, supportato da un grafico che mostra n == numero di loop e our 'growth rate'=> 10 ^ n, che NON è n. L'esempio può essere corretto facendo n=# horses, che richiede restrizioni per il log n loop. Cattivi esempi pedogogici producono studenti che credono solo di capire.
psimpson,

56

Puoi pensare a O (log N) intuitivamente dicendo che il tempo è proporzionale al numero di cifre in N.

Se un'operazione esegue un lavoro a tempo costante su ogni cifra o bit di un ingresso, l'intera operazione richiederà un tempo proporzionale al numero di cifre o bit nell'ingresso, non alla grandezza dell'ingresso; quindi, O (log N) anziché O (N).

Se un'operazione prende una serie di decisioni a tempo costante ciascuna delle quali dimezza (riduce di un fattore 3, 4, 5 ..) la dimensione dell'input da considerare, l'intero prenderà il tempo proporzionale alla base log 2 (base 3 , base 4, base 5 ...) della dimensione N dell'ingresso, anziché essere O (N).

E così via.


7
Credo che sia abbastanza preciso e più facile da comprendere della maggior parte delle spiegazioni.
T.

è una spiegazione di log<sub>10</sub> N, vero?
LiuYan 刘 研

1
@LiuYan 刘 研 non hanno detto in quale base si trovava il numero di cifre. In ogni caso, log₂ (n) = log₁₀ (n) / log₁₀ (2) e 1 / log₁₀ (2) è quindi un moltiplicatore costante, con lo stesso principio che si applica a tutte le altre basi. Questo mostra due cose. In primo luogo, il principio del moonshadow si applica qualunque sia la base (sebbene più bassa sia la base, meno "jags" nella stima) e anche che O (log n) è O (log n) indipendentemente dalla base del calcolo che ti ha portato a quella conclusione .
Jon Hanna,

"proporzionale" ... "ciascuno dei quali dimezza la dimensione dell'ingresso" ??????
csguy,

52

Il modo migliore che ho sempre dovuto visualizzare mentalmente un algoritmo che gira in O (log n) è il seguente:

Se aumenti la dimensione del problema per un importo moltiplicativo (cioè moltiplica la sua dimensione per 10), il lavoro viene aumentato solo di un importo aggiuntivo.

Applicando questo alla domanda dell'albero binario in modo da avere una buona applicazione: se si raddoppia il numero di nodi in un albero binario, l'altezza aumenta solo di 1 (una quantità aggiuntiva). Se lo raddoppi di nuovo, aumenta ancora solo di 1. (Ovviamente suppongo che rimanga equilibrato e così via). In questo modo, invece di raddoppiare il tuo lavoro quando si moltiplicano le dimensioni del problema, stai facendo solo un po 'più di lavoro. Ecco perché gli algoritmi O (log n) sono fantastici.


52

Per prima cosa ti consiglio di leggere il seguente libro;

Algorithms (4th Edition)

Ecco alcune funzioni e le loro complessità previste. I numeri indicano le frequenze di esecuzione delle istruzioni .

Ecco alcune funzioni e le loro complessità previste

Seguendo il grafico della complessità di Big-O anche preso da bigocheatsheet Grafico della complessità di Big-O

Infine, la vetrina molto semplice mostra come viene calcolato;

Anatomia delle frequenze di esecuzione dell'istruzione di un programma.

Analisi del tempo di esecuzione di un programma (esempio).

Analizzare il tempo di esecuzione di un programma


5
Non metterei O (n log n) nel cestino difettoso . Appartiene a quello giusto .
André Werlang,

Quando si visualizza il grafico della complessità big-O (sopra), è necessario ricordare che O (n) è il punto lineare effettivo, non il bordo rosa / arancione. @Andre Ecco perché O (n log n) è correttamente contrassegnato nella fascia di prestazioni "cattiva", è una prestazione peggiore di quella lineare.
JavaBeast

@JavaBeast corretto, mentre le prestazioni di O (n log n) sono tecnicamente peggiori di O (n), fare riferimento alla tabella sopra, che presenta un buon confronto tra loro (vedere la crescita dei due). anche il grafico, da una fonte diversa, è contraddittorio perché mette O (1) e O (log n) nello stesso buono / eccellente. il loro ordine relativo di crescita è paragonabile a O (n) e O (n log n). tl; dr; O (n log n) non è eccellente, ma è tutt'altro che male.
André Werlang

1
Questa risposta è sbagliata! Presuppone che N = N * N. In effetti N = N! Il tuo esempio è in realtà N cubato. Fai lo stesso nel tuo grafico. La tua O (n) dovrebbe effettivamente essere la divisione tra orribile e cattivo. Prova matematica: dici che per loop è costante con O (1). Questo è il vero significato di 1, non dipendente da N. Significa semplicemente non variabile. Ma è variabile in quanto dipende da N. due volte N e metà del tempo. Pertanto non è valido. Se proviene da quel libro, non comprarlo! La grafica del codice che hai mostrato non è reale, è uno scherzo, guarda "Fantastico", significa che tre persone fanno sesso contemporaneamente! OMG
jgmjgm

1
O (n) non dovrebbe essere sulla diagonale?
Gyosifov,

46

Che cos'è il registro b (n)?

È il numero di volte in cui è possibile tagliare ripetutamente un tronco di lunghezza n in b parti uguali prima di raggiungere una sezione di dimensione 1.


Ottimo commento! È concisa ed esattamente la risposta che sto cercando.
DennisL,

18

Gli algoritmi di divisione e conquista di solito hanno a logn componente per il tempo di esecuzione. Ciò deriva dal dimezzamento ripetuto dell'ingresso.

Nel caso della ricerca binaria, ogni iterazione viene eliminata metà dell'input. Va notato che nella notazione Big-O, log è log base 2.

Modifica: come notato, la base log non ha importanza, ma quando si ricava la prestazione Big-O di un algoritmo, il fattore log verrà dimezzato, quindi perché lo considero come base 2.


2
Perché è log base 2? In quicksort randomizzato, ad esempio, non penso che sia base 2. Per quanto ne so, la base non ha importanza, poiché base log a (n) = log2 (n) / log2 (a), quindi ogni logaritmo è diverso da un altro per una costante e le costanti sono ignorate nella notazione big-o. In effetti, scrivere la base di un registro in notazione big-o è un errore secondo me, poiché stai scrivendo una costante.
IVlad


È vero che può essere convertito in qualsiasi base e non importa, ma se stai provando a ricavare le prestazioni Big-O e vedi un dimezzamento costante, aiuta a capire che non vedrai la base log 10 riflessa nel codice.
David Kanarek,

A parte: in cose come gli alberi B, dove i nodi hanno un fan-out di più di 2 (cioè "più largo" di un albero binario), vedrai comunque la crescita di O (logn), perché è ancora divisa e -conquer, ma la base del log sarà correlata al fan-out.
Roger Lipscombe,

La digressione sul registro 2 è stata piuttosto utile, in realtà.
Dan Rosenstark,

15

Ma cos'è esattamente O (log n)? Ad esempio, cosa significa che l'altezza di un> albero binario completo è O (log n)?

Lo riformulerei come 'l'altezza di un albero binario completo è log n'. Immaginare l'altezza di un albero binario completo sarebbe O (log n), se avessi attraversato passo dopo passo.

Non riesco a capire come identificare una funzione con un tempo logaritmico.

Il logaritmo è essenzialmente l'inverso dell'espiazione. Quindi, se ogni 'passaggio' della tua funzione sta eliminando un fattore di elementi dal set di oggetti originale, questo è un algoritmo di tempo logaritmico.

Per l'esempio dell'albero, puoi facilmente vedere che abbassare un livello di nodi riduce un numero esponenziale di elementi mentre continui a attraversare. L'esempio popolare di guardare attraverso una rubrica ordinata per nome equivale essenzialmente a attraversare un albero di ricerca binario (la pagina centrale è l'elemento radice e puoi dedurre ad ogni passaggio se andare a sinistra oa destra).


3
+1 per menzionare "Il logaritmo è essenzialmente l'inverso dell'esponenziazione".
Talonx,

12

Questi 2 casi impiegheranno il tempo O (log n)

case 1: f(int n) {
      int i;
      for (i = 1; i < n; i=i*2)
        printf("%d", i);
    }


 case 2  : f(int n) {
      int i;
      for (i = n; i>=1 ; i=i/2)
        printf("%d", i);
    }

Sono sicuro che mi manca qualcosa, ma non sarei sempre zero e i loop corrono per sempre in entrambi i casi, poiché 0 * 2 = 0 e 0/2 = 0?
dj_segfault,

2
@dj_segfault, è stato un mio errore. Penso che ora abbia un senso .. :)
Ravi Bisla,

@RaviBisla Altre risposte affermano che un input di 10 richiederebbe 1 volta fino a 10 loop e un input di 100 richiederebbe 3 volte il tempo di input di 1, questo non è sicuramente il caso di quegli esempi. stackoverflow.com/a/2307330/1667868
Sven van den Boogaart,

12

O (log n) è un po 'fuorviante, più precisamente è O (log 2 n), cioè (logaritmo con base 2).

L'altezza di un albero binario bilanciato è O (log 2 n), poiché ogni nodo ha due nodi secondari (notare i "due" come nel log 2 n). Quindi, un albero con n nodi ha un'altezza del registro 2 n.

Un altro esempio è la ricerca binaria, che ha un tempo di esecuzione di O (log 2 n) perché ad ogni passaggio si divide lo spazio di ricerca per 2.


4
O (log n) è lo stesso ordine di O (ld n) o O (LN n). Sono proporzionali. Capisco che ai fini dell'apprendimento è più facile usare ld.
helios,

4
"più precisamente è O (ld n)" - No, non lo è: tutti i registri sono dello stesso ordine (ognuno differisce dagli altri solo per un fattore di ridimensionamento costante, che viene ignorato / ignorabile).
ChrisW,

1
hai ragione Chris, pessima formulazione. avrebbe dovuto dirlo come ha fatto Helios. aiuta per l'apprendimento / comprensione ma alla fine tutti i registri sono dello stesso ordine.
stmax,

10

O(log n) si riferisce a una funzione (o algoritmo, o passaggio in un algoritmo) che lavora in un periodo di tempo proporzionale al logaritmo (di solito base 2 nella maggior parte dei casi, ma non sempre, e in ogni caso questo è insignificante dalla notazione big-O *) della dimensione dell'input.

La funzione logaritmica è l'inverso della funzione esponenziale. Detto in altro modo, se l'input cresce in modo esponenziale (anziché in modo lineare, come si considererebbe normalmente), la funzione aumenta in modo lineare.

O(log n)i tempi di esecuzione sono molto comuni in qualsiasi tipo di applicazione di divisione e conquista, perché stai (idealmente) tagliando il lavoro a metà ogni volta. Se in ciascuna delle fasi di divisione o conquista, stai facendo un lavoro a tempo costante (o un lavoro che non è un tempo costante, ma con un tempo che cresce più lentamente di O(log n)), allora tutta la tua funzione è O(log n). È piuttosto comune che ogni passaggio richieda invece un tempo lineare sull'input; ciò equivarrà a una complessità temporale totale diO(n log n) .

La complessità del tempo di esecuzione della ricerca binaria è un esempio di O(log n). Questo perché nella ricerca binaria, stai sempre ignorando metà dell'input in ogni passaggio successivo dividendo l'array a metà e concentrandoti solo sulla metà con ogni passaggio. Ogni passaggio è a tempo costante, perché nella ricerca binaria devi solo confrontare un elemento con la tua chiave per capire cosa fare dopo indipendentemente dalla grandezza dell'array che stai considerando in qualsiasi momento. Quindi esegui circa i passaggi log (n) / log (2).

La complessità del tempo di esecuzione dell'ordinamento unione è un esempio di O(n log n). Questo perché stai dividendo l'array a metà con ogni passaggio, risultando in un totale di circa log (n) / log (2) passaggi. Tuttavia, in ogni passaggio è necessario eseguire operazioni di unione su tutti gli elementi (che si tratti di un'operazione di unione su due elenchi secondari di n / 2 elementi o di due operazioni di unione su quattro elenchi secondari di n / 4 elementi, è irrilevante perché aggiunge la necessità di dover fai questo per n elementi in ogni passaggio). Quindi, la complessità totale è O(n log n).

* Ricorda che la notazione big-O, per definizione , le costanti non contano. Inoltre, cambiando la regola di base per i logaritmi, l'unica differenza tra i logaritmi di basi diverse è un fattore costante.


L'ultima * nota ha risolto la mia confusione sul fatto che i logaritmi si basassero su 2 o 10 :) Grazie mille.
yahya,


9

In poche parole: ad ogni passo del tuo algoritmo puoi dimezzare il lavoro. (Equivalente asintoticamente al terzo, quarto, ...)


2
Questa risposta è molto imprecisa. Prima di tutto, puoi pensare di dimezzare il lavoro solo nel caso del logaritmo in base 2. È davvero incredibile come questa risposta (e la maggior parte delle risposte alla domanda originale) abbia ricevuto così tanti voti positivi. "(Equivalente asintoticamente al terzo, quarto, ...)"? Perché rispondere a una domanda se non hai tempo?
nbro,

8

Se traccia una funzione logaritmica su una calcolatrice grafica o qualcosa di simile, vedrai che sale molto lentamente, anche più lentamente di una funzione lineare.

Questo è il motivo per cui gli algoritmi con una complessità temporale logaritmica sono molto ricercati: anche per n veramente grandi (diciamo n = 10 ^ 8, per esempio), si comportano in modo più che accettabile.


7

Ma cos'è esattamente O (log n)

Ciò che significa precisamente è "come ntende verso infinity, la timetendenza verso a*log(n)dove aè un fattore di ridimensionamento costante".

O in realtà, non significa proprio questo; più probabilmente significa qualcosa come " timediviso per a*log(n)tende verso 1".

"Tende verso" ha il solito significato matematico da "analisi": per esempio, "se si sceglie una costante diversa da zero arbitrariamente piccola k, allora posso trovare un valore corrispondente Xtale che ((time/(a*log(n))) - 1)sia inferiore rispetto ka tutti i valori nmaggiori di X".


In parole povere, significa che l'equazione del tempo può avere alcuni altri componenti: ad esempio può avere un tempo di avvio costante; ma questi altri componenti impallidiscono verso l'insignificanza per grandi valori di n, e a * log (n) è il termine dominante per grande n.

Si noti che se l'equazione fosse, ad esempio ...

tempo (n) = a + b log (n) + c n + d n n

... allora questo sarebbe O (n al quadrato) perché, indipendentemente dai valori delle costanti a, b, c e non zero d, il d*n*ntermine dominerebbe sempre sugli altri per qualsiasi valore sufficientemente grande di n.

Questo è ciò che significa la notazione bit O: significa "qual è l'ordine del termine dominante per qualsiasi n sufficientemente grande".



7

Posso aggiungere qualcosa di interessante, che ho letto nel libro di Kormen ecc. Molto tempo fa. Ora, immagina un problema, in cui dobbiamo trovare una soluzione in uno spazio problematico. Questo spazio problematico dovrebbe essere limitato.

Ora, se puoi provare, che ad ogni iterazione del tuo algoritmo tagli una frazione di questo spazio, che non è inferiore a qualche limite, ciò significa che il tuo algoritmo viene eseguito nel tempo O (logN).

Vorrei sottolineare che stiamo parlando di un limite di frazione relativa, non di quello assoluto. La ricerca binaria è un esempio classico. Ad ogni passo buttiamo via 1/2 dello spazio problematico. Ma la ricerca binaria non è l'unico esempio del genere. Supponiamo che tu abbia dimostrato in qualche modo che ad ogni passo butti via almeno 1/128 di spazio problematico. Ciò significa che il programma è ancora in esecuzione al momento O (logN), sebbene significativamente più lento della ricerca binaria. Questo è un ottimo suggerimento per l'analisi degli algoritmi ricorsivi. Spesso si può dimostrare che ad ogni passo la ricorsione non utilizzerà diverse varianti e questo porta al taglio di una frazione dello spazio problematico.


6

Posso fare un esempio per un ciclo for e forse una volta afferrato il concetto forse sarà più semplice da capire in contesti diversi.

Ciò significa che nel ciclo il passo cresce esponenzialmente. Per esempio

for (i=1; i<=n; i=i*2) {;}

La complessità nella notazione O di questo programma è O (log (n)). Proviamo a farne un giro manualmente (n si trova tra 512 e 1023 (escluso 1024):

step: 1   2   3   4   5    6    7    8     9     10
   i: 1   2   4   8   16   32   64   128   256   512

Sebbene n sia compreso tra 512 e 1023, si verificano solo 10 iterazioni. Questo perché il passaggio nel ciclo cresce in modo esponenziale e richiede quindi solo 10 iterazioni per raggiungere la terminazione.

Il logaritmo di x (alla base di a) è la funzione inversa di a ^ x.

È come dire che il logaritmo è l'inverso dell'esponenziale.

Ora prova a vederlo in questo modo, se l'esponenziale cresce molto velocemente, il logaritmo cresce (inversamente) molto lentamente.

La differenza tra O (n) e O (log (n)) è enorme, simile alla differenza tra O (n) e O (a ^ n) (un essere una costante).


6

In realtà, se hai un elenco di n elementi e crei un albero binario da quell'elenco (come nell'algoritmo divide and conquer), continuerai a dividere per 2 fino a raggiungere elenchi di dimensione 1 (le foglie).

Al primo passo, dividi per 2. Hai quindi 2 liste (2 ^ 1), dividi ognuna per 2, quindi hai 4 liste (2 ^ 2), dividi di nuovo, hai 8 liste (2 ^ 3) ) e così via fino a quando la dimensione dell'elenco è 1

Questo ti dà l'equazione:

n/(2^steps)=1 <=> n=2^steps <=> lg(n)=steps

(prendi la LG di ogni lato, LG è la base di registro 2)


2
Fino a quando alcuni malware non iniziano a inserire un nuovo elenco con lunghezza x a due livelli prima dei nodi lascia. Quindi sembrerà un ciclo infinito ...
Francis Cugler,

1
Non ho ricevuto il tuo commento. La mia spiegazione è sbagliata?
Dinaiz,

1
Stavo solo facendo uno scherzo ipotetico. Non intendevo davvero nulla.
Francis Cugler,

6

Ogni volta che scriviamo un algoritmo o un codice proviamo ad analizzarne la complessità asintotica. È diverso dalla sua complessità temporale .

La complessità asintotica è il comportamento del tempo di esecuzione di un algoritmo mentre la complessità temporale è il tempo di esecuzione effettivo. Ma alcune persone usano questi termini in modo intercambiabile.

Perché la complessità temporale dipende da vari parametri, vale a dire.
1. Sistema fisico
2. Linguaggio di programmazione
3. Stile di codifica
4. E molto altro ancora ......

Il tempo di esecuzione effettivo non è una buona misura per l'analisi.


Invece prendiamo la dimensione di input come parametro perché qualunque sia il codice, l'input è lo stesso. Quindi il tempo di esecuzione è una funzione della dimensione dell'input.

Di seguito è riportato un esempio di algoritmo del tempo lineare


Ricerca lineare
Dato n elementi di input, per cercare un elemento nell'array è necessario al massimo 'n' confronti . In altre parole, non importa quale linguaggio di programmazione usi, quale stile di codifica preferisci, su quale sistema lo esegui. Nel peggiore dei casi richiede solo n confronti. Il tempo di esecuzione è linearmente proporzionale alla dimensione dell'input.

E non è solo ricerca, qualunque sia il lavoro (incremento, confronto o qualsiasi altra operazione) è una funzione della dimensione dell'input.

Quindi, quando si dice che qualsiasi algoritmo è O (log n) significa che il tempo di esecuzione è log volte la dimensione di input n.

All'aumentare della dimensione dell'input aumenta il lavoro svolto (qui il tempo di esecuzione) (quindi proporzionalità)

      n      Work
      2     1 units of work
      4     2 units of work
      8     3 units of work

Vedi come aumentano le dimensioni di input, il lavoro svolto viene aumentato ed è indipendente da qualsiasi macchina. E se provi a scoprire il valore delle unità di lavoro, in realtà dipende da quei parametri sopra specificati, cambierà in base ai sistemi e tutto il resto.


5

Albero

log x to base b = y è l'inverso di b^y = x

Se hai un albero M-ary di profondità d e dimensione n, allora:

  • attraversando l'intero albero ~ O (M ^ d) = O (n)

  • Percorrendo un singolo sentiero nell'albero ~ O (d) = O (accedi n alla base M)


5

Nella tecnologia dell'informazione significa che:

  f(n)=O(g(n)) If there is suitable constant C and N0 independent on N, 
  such that
  for all N>N0  "C*g(n) > f(n) > 0" is true.

Formica sembra che questa notazione sia stata per lo più presa dalla matematica.

In questo articolo c'è una citazione: DE Knuth, "BIG OMICRON E BIG OMEGA E BIG THETA", 1976 :

Sulla base delle questioni discusse qui, propongo che i membri di SIGACT, e redattori di riviste di informatica e matematica, adottino le notazioni come sopra definite, a meno che non si possa trovare ragionevolmente presto un'alternativa migliore .

Oggi è il 2016, ma lo usiamo ancora oggi.


Nell'analisi matematica significa che:

  lim (f(n)/g(n))=Constant; where n goes to +infinity

Ma anche nell'analisi matematica a volte questo simbolo è stato usato nel significato di "C * g (n)> f (n)> 0".

Come noto all'università, il simbolo fu introdotto dal matematico tedesco Landau (1877-1938)


4

L'esempio binario completo è O (ln n) perché la ricerca è simile alla seguente:

1 2 3 4 5 6 7 8 9 10 11 12

La ricerca di 4 produce 3 risultati: 6, 3 e 4. E log2 12 = 3, che è una buona stima del numero di hit necessari.


grazie per l'esempio. Indica chiaramente come il nostro algoritmo può usare il tempo logaritmico nel metodo divide and conquer.
Abc

Quindi se è un ciclo di n / 2 è sempre log (n)?
Gil Beyruth,

3

Se stai cercando una risposta basata sull'intuizione, vorrei fare due interpretazioni per te.

  1. Immagina una collina molto alta con una base molto ampia. Per raggiungere la cima della collina ci sono due modi: uno è un sentiero dedicato che gira a spirale attorno alla collina che raggiunge in cima, l'altro: una piccola terrazza come intagli ritagliati per fornire una scala. Ora se il primo modo sta raggiungendo in tempo lineare O (n), il secondo è O (log n).

  2. Immagina un algoritmo, che accetta un numero intero, ncome input e si completa in un tempo proporzionale a nallora è O (n) o theta (n) ma se funziona in tempo proporzionale a number of digits or the number of bits in the binary representation on numberallora l'algoritmo viene eseguito in O (log n) o theta (log n) tempo.


per favore modifica. ha "O (n) o theta (n)" in entrambi gli scenari ...? Inoltre, ho sentito molto questo, la dimensione rispetto alle # cifre. Stiamo dicendo dimensioni === 128 per n = 10000000 e cifre === 8 per n = 10000000? Per favore, chiarisci.
Cody,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.