Can anyone suggest time complexity of the following code - c++

According to me the time complexity should be O(nlogn) as the outer loop works until n/2^k =1 and inner loop works for n times. Can anyone tell if i'm correct or not.
while(n){
j=n;
while(j>1){
j-=1;
}
n/=2;
}

Inner cycle does n iterations, outer each iteration divides n by 2, so there are n + n/2 + n/4 + ... = 2n total iterations of the inner cycle and time complexity is O(n), not O(n log n).

Related

How can we compute the time complexity of the below function

void f(int n)
{
doOh(n);
if(n<1) return;
for(int i=0; i<2; i++)
{
f(n/2);
}
}
Time complexity of doOh(n) is O(N).
How can we compute the time complexity of the given function.
Denoting the complexity as T(n), the code says
T(n) = T0 if n = 0
= O(n) + 2 T(n/2) otherwise
We can get an upper bound by replacing O(n) with c n for some c*, and we expand
T(n) = c n + 2 T(n/2)
= c n + 2 c n/2 + 4 T(n/4)
= c n + 2 c n/2 + 4 c n/4 + 8 T(n/8)
= ...
The summation stops when n < 2^l, where l is the number of significant bits of n. Hence we conclude that
T(n) = O(l c n + 2^l T0) = O(l n).
*Technically, we can only do that as of n > some N. But this does not change the conclusion regarding the asymptotic behavior of T.
Complexity = O(nlog2n)
The reason is
Every time f(n) is called, doOh(n) is called. Its time complexity is O(n) when we pass n in f(n) as you mentioned
f(n) will call f(n/2) 2 times. So time complexity will be 2*O(f(n/2)) = O(f(n/2))
f(n) is becoming f(n/2). f(n/2) is becoming f(n/4) and so on... it means this f(n) will be called log2n times (logn base 2 times).
Hence, doOh(n) will also create n + n/2 + n/4 and so on time complexity logn times.
n or n/2 or n/4 all have O(n) complexity.
Hence the total time complexity is O(logn) * O(n) which is order of nlogn base 2 = O(nlog2n)

Time complexity n^2

Is this O(N^2) or O(nlogn). Isnt it n^2 when there are nested loops?
int a[], N;
int f1(){ int i, j, sum=0;
for (i=1;; i=2*i)
{
If (i>=N) return sum;
for (j=1; j<2*i;j++) sum+=a[i];
}
This is O(N log N) as the outer loop is doubling the value of i in every iteration. So the complexity of outer loop is O(log N) instead of O(N).
If you had i++ or similar instead of i=2*i then the time complexity of two loops would have been O(n^2).
Edit: this is a simplified analysis. Please see the answer from R Sahu for more rigorous analysis.
Is this O(N^2) or O(nlogn).
It is neither.
Isnt it n^2 when there are nested loops?
That is true when you iterate over the items linearly. That is not true in your case.
In your case ...
The values of i are: 1 2 4 8 16 ... N
The inner loop is executed 2 + 4 + 8 + 16 + 32 ... N times.
That is a geometric series. The sum of a geometric series is a(1 - r^n)/(1 - r).
In your case, a is 2, r is 2, and n is log2(N) (log with base 2). Hence, the sum, after some simplification, is 2*2^(log2(N)), which is same as 2*N.
i.e your algorithmic complexity is O(N).
Thanks are due to #LedHead for correcting the error in the initial post.

Calculating the Time Complexity of nested loop with logarithmic increase

I am learning at my own pace online. I was solving some examples but I can't wrap my mind around this one:
while(i<n)
{
for(int j=1; j<=i; j++)
sum = sum + 1;
i *=2;
}
I think the answer should be 2^n but my friend says nlog(n)
Can someone find the big-O for this loop and explain to me how to do so?
The outer loop will enter it's body log2(n) times, because i is increasing exponentially and thereby reaches the end n faster and faster. For example, if n were 1024, it would need only 10 iterations, with n=65536, it were 16 iterations. The accurate count is log2(n), but in terms of runtime complexity the logarithmic behaviour is enough. So here the complexity is O(log(n)).
The inner loop for(int j=1; j<=i; j++), each time when evaluated, will run to the corresponding i. It can be shown that the average run width is about n / log2(n), since i is 1, 2, 4, ... n with log2(n) steps. For example, if n is 31, i is 1, 2, 4, 8, 16, the sum is 31 with 5 steps. So it is permissible to take complexity O(n/log(n)) here.
The overal complexity is then O(log(n)*n/log(n)), which is O(n).
It's n.
if n=2^k then while complexity is k,
second loop : 2^1 + 2^2 + ... 2^k = 2^(k+1)-1 ~= 2^(k+1)
2^(k+1) = 2*n
We can assume without loss of generality that N is equal to 2^k + 1. We need to find the number of iterations of the inner loop. There will be k iterations of outer loop with 2^0, 2^1, ..., 2^k iterations of the inner loop. Let's sum up this values.

Time complexity with log in loop

what is the complexity of a loop which goes this
for (int i = 0; i < n; i++)
{
for (int j = 0; j < log(i); j++)
{
// do something
}
}
According to me the inner loop will be running log(1)+log(2)+log(3)+...+log(n) times so how do i calculate its complexity?
So, you have a sum log(1) + log(2) + log(3) + ... + log(n) = log(n!). By using Stirling's approximation and the fact that ln(x) = log(x) / log(e) one can get
log(n!) = log(e) * ln(n!) = log(e) (n ln(n) - n + O(ln(n)))
which gives the same complexity O(n ln(n)) as in the other answer (with slightly better understanding of the constants involved).
Without doing this in a formal manner, such complexity calculations can be "guessed" using integrals. The integrand is the complexity of do_something, which is assumed to be O(1), and combined with the interval of log N, this then becomes log N for the inner loop. Combined with the outer loop, the overall complexity is O(N log N). So between linear and quadratic.
Note: this assumes that "do something" is O(1) (in terms of N, it could be of a very high constant of course).
Lets start with log(1)+log(2)+log(3)+...+log(n). Roughly half of the elements of this sum are greater than or equal to log(n/2) = log(n) - log(2). Hence the lower bound of this sum is n / 2 * (log(n) - log(2)) = Omega(nlog(n)). To get upper bound simply multiply n by the largest element which is log(n), hence O(nlog(n)).

What is the algorithmic complexity of the code below

Is the Big-O for the following code O(n) or O(log n)?
for (int i = 1; i < n; i*=2)
sum++;
It looks like O(n) or am I missing this completely?
It is O(logn), since i is doubled each time. So at overall you need to iterate k times, until 2^k = n, and in this case it happens when k = logn (since 2^logn = n).
Simple example: Assume n = 100 - then:
iter1: i = 1
iter2: i = 2
iter3: i = 4
iter4: i = 8
iter5: i = 16
iter6: i = 32
iter7: i = 64
iter8: i = 128 > 100
It is easy to see that an iteration will be added when n is doubled, which is logarithmic behavior, while linear behavior is adding iterations for a constant increase of n.
P.S. (EDIT): mathematically speaking, the algorithm is indeed O(n) - since big-O notation gives asymptotic upper bound, and your algorithm runs asymptotically "faster" then O(n) - so it is indeed O(n) - but it is not a tight bound (It is not Theta(n)) and I doubt that is actually what you are looking for.
The complexity is O(logn) because the loops runs (log2n - 1) times.
O(log(n)), as you only loop ~log2(n) times
No the complexity is not linear. Try to play through a few scenarios: how many iterations does this cycle do for n = 2, n=4, n=16, n=1024? How about for n = 1024 * 1024? Maybe this will help you get the correct answer.
For loop check runs lg(n) +1 times. The inner loop runs lg(n) times. So, the complexity is is O(lg n), not O(log n).
If n==8, the following is how the code will run:
i=1
i=2
i=4
i=8 --Exit condition
It is O(log(n)).
Look at the code num++;
It loops O(log(n)) times.