2012-09-05 8 views
8

In dem Buch Programmierung Interviews ausgesetzt heißt es, dass die Komplexität des Programms unten ist O (N), aber ich verstehe nicht, wie das möglich ist. Kann jemand erklären, warum das so ist?Was ist die Komplexität dieses Codes, dessen verschachtelte for-Schleife seinen Zähler wiederholt verdoppelt?

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

* "Er sagt:" * Was sagt? Sag uns, was immer du hier anstellst. – dmckee

+0

Ich habe die Bearbeitung gemacht, sorry über die Vagheit –

+0

Diese Schleifenstruktur ist sehr eng mit der für den Heap-Algorithmus verbunden und die Analyse wird sehr ähnlich sein. – templatetypedef

Antwort

15

Sie brauchen ein bisschen Mathe, um das zu sehen. Die innere Schleife iteriert Θ(1 + log [N/(i+1)]) mal (die 1 + ist notwendig, da für i >= N/2, [N/(i+1)] = 1 und der Logarithmus ist 0, noch die Schleife iteriert einmal). j nimmt den Wert (i+1)*2^k, bis es zumindest so groß wie N ist, und

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

mathematische Abteilung mit. Also wird das Update j *= 2ceiling(log_2 (N/(i+1))) mal aufgerufen und die Bedingung 1 + ceiling(log_2 (N/(i+1))) mal überprüft. So können wir die gesamte Arbeit

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

Jetzt schreiben, Stirling's formula sagt uns

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

so finden wir die gesamte geleistete Arbeit in der Tat O(N) ist.

+0

Kudos für die ASCII-Gleichungen/art – meowgoesthedog

1

@Daniel Fischers Antwort ist korrekt.

würde Ich mag die Tatsache hinzufügen, dass genau dieses Laufzeit des Algorithmus ist wie folgt:

enter image description here

Was bedeutet:

enter image description here

4

äußere Schleife läuft n mal. Jetzt hängt alles von der inneren Schleife ab.
Die innere Schleife ist jetzt die knifflige.

Lets folgen:

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

Meinen Sie "j" statt "i" in der zweiten Box? – meowgoesthedog

+0

@meowgoesthedog, nein. Ich meinte "i", wenn die äußere Schleife in diesen Bereichen ist, wird j zugewiesen "1 2 3 4 5 ..." verschiedene Werte (Anzahl der Iterationen) BTW, netter Reputationsgewinn :). Vor wenigen Tagen hatten Sie 800 ~ –

+0

Aber 'j' ist die Variable, die exponentiell wächst, nicht linear wie' i'? Und ich glaube nicht, dass die Anzahl der Iterationen linear zunimmt, wie Sie gesagt haben. – meowgoesthedog