2012-09-05 17 views
8

Nel libro Interviste di programmazione Exposed dice che la complessità del programma qui sotto è O (N), ma non capisco come sia possibile. Qualcuno può spiegare perché questo è?Qual è la complessità di questo codice il cui ciclo annidato per ripetutamente raddoppia il contatore?

int var = 2; 
for (int i = 0; i < N; i++) { 
    for (int j = i+1; j < N; j *= 2) { 
     var += var; 
    } 
} 
+1

* "si dice" * Che cosa dice? Dicci qualunque cosa tu stia assumendo qui. – dmckee

+0

Ho apportato la modifica, mi dispiace per la vaghezza –

+0

Questa struttura ad anello è strettamente correlata a quella per l'algoritmo di heapify e l'analisi sarà molto simile. – templatetypedef

risposta

15

Hai bisogno di un po 'di matematica per vederlo. Il ciclo interno itera Θ(1 + log [N/(i+1)]) volte (lo 1 + è necessario poiché per i >= N/2, [N/(i+1)] = 1 e il logaritmo è 0, eppure il ciclo itera una volta). j assume i valori (i+1)*2^k finché è almeno grande quanto N, e

(i+1)*2^k >= N <=> 2^k >= N/(i+1) <=> k >= log_2 (N/(i+1)) 

utilizzando divisione matematica. Quindi l'aggiornamento j *= 2 si chiama ceiling(log_2 (N/(i+1))) volte e la condizione è selezionata 1 + ceiling(log_2 (N/(i+1))) volte. Così possiamo scrivere il lavoro totale

N-1         N 
∑ (1 + log (N/(i+1)) = N + N*log N - ∑ log j 
i=0         j=1 
         = N + N*log N - log N! 

Ora, Stirling's formula ci dice

log N! = N*log N - N + O(log N) 

così troviamo il lavoro totale fatto è davvero O(N).

+0

kudos per le equazioni ASCII/art – meowgoesthedog

1

@Daniel La risposta di Fischer è corretta.

vorrei aggiungere il fatto che il tempo esatto in esecuzione di questo algoritmo è il seguente:

enter image description here

Il che significa:

enter image description here

4

ciclo esterno viene eseguito n volte. Ora tutto dipende dal ciclo interno.
Il ciclo interno ora è il difficile.

Lets seguono:

i=0 --> j=1    ---> log(n) iterations 
... 
... 
i=(n/2)-1 --> j=n/2  ---> 1 iteration. 
i=(n/2) --> j=(n/2)+1 --->1 iteration. 

i > (n/2)   ---> 1 iteration 
(n/2)-1 >= i > (n/4) ---> 2 iterations 
(n/4) >= i > (n/8) ---> 3 iterations 
(n/8) >= i > (n/16) ---> 4 iterations 
(n/16) >= i > (n/32) ---> 5 iterations 

(n/2)*1 + (n/4)*2 + (n/8)*3 + (n/16)*4 + ... + [n/(2^i)]*i 

    N-1         
n*∑ [i/(2^i)] =< 2*n 
    i=0 

--> O(n) 
+0

Intendevi 'j' invece di' i' nella seconda casella? – meowgoesthedog

+0

@meowgoesthedog, no. Intendevo 'i', quando il ciclo esterno si trova in questi intervalli, j verrà assegnato a' 1 2 3 4 5 ... 'valori diversi (numero di iterazioni) BTW, guadagno di buona reputazione :). Pochi giorni fa avevi 800 ~ –

+0

Ma 'j' è la variabile che cresce esponenzialmente, non linearmente come' i'? E non penso che il numero di iterazioni aumenti in modo lineare come hai detto tu. – meowgoesthedog

Problemi correlati