for (i = 1; i <= n; i *= 2)
for (j = 1; j <= i; j++)
sum++;
I think it's time complexity is O(n) (1 + 2 + 2 + 3 + 3 + 3 ... = (1(2^(log2n)-1))/(2-1), sum of geometric sequence). Is it right? I'm confused with my answser.
i changes in these steps: 1, 2, 2^2, ..., 2^log(n) and in each iteration of the outer loop, the inner loop run i times. Hence, the time complexity T(n) is 1 + 2 + 2^2 + ... + 2^log(n) which is equal to 2^{log(n) + 1} -1. Threfore, T(n) = Theta(n).
Related
This code snippet is suppose to have a complexity of O(n). Yet, I don't understand why.
sum = 0;
for (k = 1; k <= n; k *= 2) // For some arbitrary n
for (j = 1; j <= k; j++)
sum++;
Now, I understand that the outer loop by itself is O(log n), so why is it that adding the inner loop makes this O(n).
Let's assume that n is a power of 2 for a moment.
The final iteration of the inner loop will run n times. The iteration before that will run n/2 times, the second-to-last iteration n/4 times, and so on up until the first iteration which will run once. This forms a series which sums to 2n − 1 total iterations. This is O(n).
(For example, with n = 16, the inner loop runs 1 + 2 + 4 + 8 + 16 = 31 total times.)
Let m = floor(lg(n)). Then 2^m = C*n with 1 <= C < 2. The number k of steps in the inner loop goes like:
1, 2, 4, 8, ..., 2^m = 2^0, 2^1, ..., 2^m
Therefore the total number of operations is
2^0 + 2^1 + ... + 2^m = 2^{m+1} - 1 ; think binary
= 2*2^m - 1
= 2*C*n - 1 ; replace
= O(n)
This question already has answers here:
Time complexity for dependant nested for loop?
(3 answers)
Closed 5 years ago.
Suppose I have a code with two for-loops:
int sum = 0;
for (int i = 1; i < N; i *= 2)
for(int j = 0; j < i; j++)
sum++;
How would I find the worst-case time complexity of this code? I've looked at many tutorials on finding time complexity and I understood them. But this one just seems a bit different from those in the tutorials.
Lets do simple maths.
Value of i in each iteration goes as 1,2,4,8... (log N + 1) terms. In each iteration, the inner loop goes i times. Adding up the values of i
T(N) = 1 + 2 + ... + (log N + 1) terms i.e. GP with a = 1 and r = 2 and n = (log N + 1)
T(N) = a[(rn-1)/(r-1)]
= 1[(2(logN+1) - 1)/(2-1)]
= 2N - 1
= O(N)
So the complexity is O(N) in all scenarios.
First consider a simpler case when N=2^k+1 for some integer k. In this case the outer loop has k iterations and the overall number of operations is
T(N) = 1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 = 2N - 3.
So the worst case complexity is at least O(2N - 3) = O(N).
Now suppose 2^k + 1 < N <= 2^(k+1) for some k. Then
T(N) = 1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 < 2N = O(N)
Therefore T(N) = O(N).
What is the time complexity of this algorithm, and why?
int count = 0;
for (int i = N; i > 0; i /= 2) {
for (int j = 0; j < i; j++) {
count += 1;
}
}
The correct answer is O(n), but I am getting O(nlogn). Can anyone tell me why it's O(n)?
On the first iteration, the inner loop executes N times, and then N/2 times, and then N/4 times, and so on. This can be expressed as an infinite sum:
N + N/2 + N/4 + N/8 + N/16 + N/32 + ...
If you factor out the N from each term, you get:
N * (1 + 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + ...)
The infinite sequence in parentheses converges on the value 2 (more info on Wikipedia). Therefore, the number of operations can be simplified to:
N * 2
In terms of Big-O, the asymptotic value is within:
O(N)
You can check this by observing that the relationship in the output between N and count is linear: Ideone Demo
I was going through this question to calculate time complexity.
int fun(int n)
{
int count = 0;
for (int i = n; i > 0; i /= 2)
for (int j = 0; j < i; j++)
count += 1;
return count;
}
My first impression was O(n log n) but the answer is O(n). Please help me understand why it is O(n).
The inner loop does n iterations, then n/2, then n/4, etc. So the total number of inner loop iterations is:
n + n/2 + n/4 + n/8 + ... + 1
<= n * (1 + 1/2 + 1/4 + 1/8 + ...)
= 2n
(See Geometric series), and therefore is O(n).
For an input integer n,
for i=n, j loop will run n times,
then for i= n/2, j loop will run n/2 times,
.
.
so on,
.
.
till i=1, where j loop will run 1 time.
So,
T(n) = (n + n/2 + n/4 + n/8 + ...... + 1)
T(n) = n(1 + 1/2 + 1/4 + 1/8 + ..... + 1/n) .....(1)
let 1/n = 1/2^k
so, k = logn
now, using summation of geometric series in eq 1
T(n) = n((1-1/2^k) / 1-1/2)
T(n) = 2n(1-1/2^k)
using k = logn
T(n) = 2n(1-1/2^logn)
now for larger value of n, logn tends to infinite and 1/2^infinite will tend to 0.
so, T(n) = 2n
so, T(n) = O(n)
For a input integer n,
the innermost statement of fun() is executed following times. n + n/2 + n/4 + ... 1 So time complexity T(n) can be written as
T(n) = O(n + n/2 + n/4 + ... 1) = O(n) The value of count is also n + n/2 + n/4 + .. + 1
The outermost loop iterates in O(logn) so it is ignored as O(n) is high
let's have i and j table
where n = 8
i -> less than 0
j -> less than i
i
j
8
[0,7]
4
[0,3]
2
[0,1]
1
[0,0]
"i" which is outer loop is logn
Now check for "j" inner loop
[0, 7] -> b - a + 1 -> 8 -> n
[0, 3] -> b - a + 1 -> 4 -> n/2
[0, 1] -> b - a + 1 -> 2 -> n/4
[0, 0] -> b - a + 1 -> 1 -> n/n
if you see it's [n + n/2 + n/4....1] it's moving to infinity not logn times
it's infinite series right if we look closely it's GP with infinite series n[1 + 1/2 + 1/4 + .......] where (r < 1)
sum of series will gives us 2 (for GP proof you check google)
which is
n[1 + 1/2 + 1/4 + .......] -> 2n
so logn + 2n => O(n)
Here's the pseudocode:
Baz(A) {
big = −∞
for i = 1 to length(A)
for j = 1 to length(A) - i + 1
sum = 0
for k = j to j + i - 1
sum = sum + A(k)
if sum > big
big = sum
return big
So line 3 will be O(n) (n being the length of the array, A)
I'm not sure what line 4 would be...I know it decreases by 1 each time it is run, because i will increase.
and I can't get line 6 without getting line 4...
All help is appreciated, thanks in advance.
Let us first understand how first two for loops work
for i = 1 to length(A)
for j = 1 to length(A) - i + 1
First for loop will run from 1 to n(length of Array A) and the second for loop will depend on value of i. SO when i = 1 second for loop will run for n times..When i increments to 2 your second for loop will run for (n-1) time ..so it will go on till 1.
So your second for loop will run as follows:
n + (n - 1) + (n - 2) + (n - 3) + .... + 1 times...
You can use following formula: sum(1 to n) = N * (N + 1) / 2 which gives (N^2 + N)/2 So we have Big oh for these two loops as
O(n^2) (Big Oh of n square )
Now let us consider third loop also...
Your third for loop looks like this
for k = j to j + i - 1
But this actually means,
for k = 0 to i - 1 (you are just shifting the range of values by adding/subtracting j but number of times the loop should run will not change, as difference remains same)
So your third loop will run from 0 to 1(value of i) for first n iterations of second loop then it will run from 0 to 2(value of i) for first (n - 1) iterations of second loop and so on..
So you get:
n + 2(n-1) + 3(n-2) + 4(n-3).....
= n + 2n - 2 + 3n - 6 + 4n - 12 + ....
= n(1 + 2 + 3 + 4....) - (addition of some numbers but this can not be greater than n^2)
= `N(N(N+1)/2)`
= O(N^3)
So your time complexity will be N^3 (Big Oh of n cube)
Hope this helps!
Methodically, you can follow the steps using Sigma Notation:
Baz(A):
big = −∞
for i = 1 to length(A)
for j = 1 to length(A) - i + 1
sum = 0
for k = j to j + i - 1
sum = sum + A(k)
if sum > big
big = sum
return big
For Big-O, you need to look for the worst scenario
Also the easiest way to find the Big-O is to look into most important parts of the algorithm, it can be loops or recursion
So we have this part of the algorithm consisting of loops
for i = 1 to length(A)
for j = 1 to length(A) - i + 1
for k = j to j + i - 1
sum = sum + A(k)
We have,
SUM { SUM { i } for j = 1 to n-i+1 } for i = 1 to n
= 1/6 n (n+1) (n+2)
= (1/6 n^2 + 1/6 n) (n + 2)
= 1/6 n^3 + 2/6 2 n^2 + 1/6 n^2 + 2/6 n
= 1/6 n^3 + 3/6 2 n^2 + 2/6 n
= 1/6 n^3 + 1/2 2 n^2 + 1/3 n
T(n) ~ O(n^3)