2012-09-05 10 views
8

W książce Wywiady programistyczne Exposed mówi, że złożoność poniższego programu to O (N), ale nie rozumiem, jak to jest możliwe. Czy ktoś może wyjaśnić, dlaczego tak jest?Jaka jest złożoność tego kodu, którego zagnieżdżona pętla for wielokrotnie podwaja swój licznik?

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

* "To mówi" Co mówi? Powiedz nam, cokolwiek tu jest, zakładasz. – dmckee

+0

Zrobiłem edycję, przepraszam za niejasności –

+0

Ta struktura pętli jest bardzo ściśle powiązana z tą dla algorytmu stapiającego, a analiza będzie bardzo podobna. – templatetypedef

Odpowiedz

15

Potrzebujesz trochę matematyki, aby to zobaczyć. Wewnętrzna pętla iteruje Θ(1 + log [N/(i+1)]) razy (wymagana jest 1 +, ponieważ dla i >= N/2, i logarytmem wynosi 0, ale pętla wykonuje iteracje raz). j przyjmuje wartości (i+1)*2^k aż będzie co najmniej tak duża jak N i

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

stosując podział matematycznego. Tak więc aktualizacja j *= 2 jest nazywana ceiling(log_2 (N/(i+1))) razy i warunek jest sprawdzany 1 + ceiling(log_2 (N/(i+1))) razy. Tak więc możemy napisać całkowitą pracę

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

Teraz Stirling's formula mówi nam

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

więc znaleźć całkowita praca wykonywana jest rzeczywiście O(N).

+0

kudos dla równań ASCII/art – meowgoesthedog

1

@Daniel Odpowiedź Fischer jest poprawna.

Chciałbym dodać, że dokładny czas działa ten algorytm jest następujący:

enter image description here

Co oznacza:

enter image description here

4

zewnętrzna pętla biegnie n razy. Teraz wszystko zależy od wewnętrznej pętli.
Wewnętrzna pętla jest teraz trudna.

Pozwala śledzić:

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

Czy chodziło Ci o "j" zamiast "i" w drugim polu? – meowgoesthedog

+0

@meowgoesthedog, nie. Miałem na myśli 'i', gdy zewnętrzna pętla jest w tych zakresach, j otrzyma przypisane' 1 2 3 4 5 ... 'różne wartości (liczba iteracji) BTW, ładny zysk reputacji :). Kilka dni temu miałeś 800 ~ –

+0

Ale 'j' jest zmienną, która rośnie wykładniczo, nie liniowo jak" i "? I nie sądzę, że liczba iteracji rośnie liniowo, tak jak powiedziałeś. – meowgoesthedog

Powiązane problemy