Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the complexity of this code whose nested for loop repeatedly doubles its counter?

In the book Programming Interviews Exposed it says that the complexity of the program below is O(N), but I don't understand how this is possible. Can someone explain why this is?

int var = 2;
for (int i = 0; i < N; i++) {
   for (int j = i+1; j < N; j *= 2) {
      var += var;
   }
}
like image 315
Nick Chris Avatar asked Sep 05 '12 17:09

Nick Chris


People also ask

What is the complexity of nested for loop?

Every time the outer loop executes, the inner loop executes M times. As a result, the statements in the inner loop execute a total of N * M times. Thus, the total complexity for the two loops is O(N2).

What is the time complexity of while loop inside for loop?

the size in the for loop is increasing every time the for loop is being executed, starting at 1,2,...,n-1 and the while loop runs n-1 times. That means that the time complexity is O(n^3)?

Why are nested for loops o n 2?

The loop may, at first glance, look like O(n^2) but the inner loop maximally creates 5 iterations for every iteration of the outer loop. So we receive only 5 * n iterations in total, not something like n^2 . The complexity thus is O(n) .

When one loop is nested inside another loop which of them runs the most number of times?

These are typically used for working with two dimensions such as printing stars in rows and columns as shown below. When a loop is nested inside another loop, the inner loop runs many times inside the outer loop. In each iteration of the outer loop, the inner loop will be re-started.


2 Answers

You need a bit of math to see that. The inner loop iterates Θ(1 + log [N/(i+1)]) times (the 1 + is necessary since for i >= N/2, [N/(i+1)] = 1 and the logarithm is 0, yet the loop iterates once). j takes the values (i+1)*2^k until it is at least as large as N, and

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

using mathematical division. So the update j *= 2 is called ceiling(log_2 (N/(i+1))) times and the condition is checked 1 + ceiling(log_2 (N/(i+1))) times. Thus we can write the total work

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

Now, Stirling's formula tells us

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

so we find the total work done is indeed O(N).

like image 179
Daniel Fischer Avatar answered Nov 11 '22 04:11

Daniel Fischer


Outer loop runs n times. Now it all depends on the inner loop.
The inner loop now is the tricky one.

Lets follow:

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)
like image 35
Tony Tannous Avatar answered Nov 11 '22 06:11

Tony Tannous