Find time complexity of a nested loop - algorithm

For the loop below,
int sum = 0;
for (int i = 1; i < N; i *= 2)
for (int j = 0; j < N; j++)
sum++;
what is the time complexity and how should I think? My guess is that the outer loop runs a total of log(N). The inner loop runs N times. Therefore, the time complexity should be Nlog(N).
Am I correct?
Thanks in advance.

For the first loop, the number of iterations is equal to log2(N), as i is doubled every iteration.
For each iteration of the first loop, the second loop runs for N times.
Therefore overall time complexity = (log2(N) * N), where the function log2(x) = log(x) to the base 2.

Related

Big O Notation: Nested Loop

sum = 0;
for (i = 0; i < m; i++)
for (j = 0; j < m*m; j++)
sum++;
Been trying to figure out the time complexity of this algorithm with Big-O Notation.
I've only found out that 1- first loop counts as O(m) and 2- Second loop counts as O(m^2). But I have a single problem. Does this nested loop counts as O(m^3) or do I have to take the fastest growing function as a basis and say that this loop counts as O(m^2) ?
You have to count how many times sum++ will effectively be performed, and not speculate about the growth of the functions.
Every time the inner loop is called, it executes sum++ exactly m² times.
And the inner loop is executed exactly m times by the outer loop, hence in total m³ sum++.
Needless to say, O(m³).
What helped me in university, just think of an example - e.g. 2.
for(int i = 0; i<2; i++)
for(int j = 0; j<4; j++)
So the loop runs 8 times, which is 2 * 4 times, which is 8, which is 2*2*2, or 2³.

Find the Big O time complexity of the code

I am fairly familiar with simple time complexity regarding constant, linear, and quadratic time complexities. In simple code segments like:
int i = 0;
i + 1;
This is constant. So O(1). And in:
for (i = 0; i < N; i++)
This is linear since it iterates n+1 times, but for Big O time complexities we remove the constant, so just O(N). In nested for loops:
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
I get how we multiply n+1 by n and reach a time complexity of O(N^2). My issue is with slightly more complex versions of this. So, for example:
S = 0;
for (i = 0; i < N; i++)
for (j = 0; j < N*N; j++)
S++;
In such a case, would I be multiplying n+1 by the inner for loop time complexity, of which I presume is n^2? So the time complexity would be O(n^3)?
Another example is:
S = 0;
for (i = 0; i < N; i++)
for (j = 0; j < i*i; j++)
for (k = 0; k < j; k++)
S++;
In this case, I expanded it and wrote it out and realized that the inner, middle for loop seems to be running at an n*n time complexity, and the most inner for loop at the pace of j, which is also nxn. So in that case, would I be multiplying n+1 x n^2 x n^2, which would give me O(n^5)?
Also, I am still struggling to understand what kind of code has logarithmic time complexity. If someone could give me an algorithm or segment of code that performs at log(n) or n log(n) time complexity, and explain it, that would be much appreciated.
All of your answers are correct.
Logarithmic time complexity typically occurs when you're reducing the size of the problem by a constant factor on every iteration.
Here's an example:
for (int i = N; i >= 0; i /= 2) { .. do something ... }
In this for-loop, we're dividing the problem size by 2 on every iteration. We'll need approximately log_2(n) iterations prior to terminating. Hence, the algorithm runs in O(log(n)) time.
Another common example is the binary search algorithm, which searches a sorted interval for a value. In this procedure, we remove half of the values on each iteration (once again, we're reducing the size of the problem by a constant factor of 2). Hence, the runtime is O(log(n)).

Big O complexity of three nested loops with the last loop in an if statement

Suppose we have the following block of code:
sum = 0;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if(i == j)
for(k = 0; k < n; k++)
sum++;
In the book I'm reading it's stated that the complexity is O(n^2), thetha (n^2) to be precise, but I'm not sure why. When trying to calculate it myself I get O(n^3):
Outer loop complexity is O(n)
By the second loop the complexity gets to O(nˆ2) by following the nested loops rule
The if statement would be true n times, so by the third loop the complexity would be O(n*nˆ2)
The sum++ statement takes constant time, so complexity stays at O(nˆ3)
That's my logic, but it's flawed it seems. What is the reasoning for the O(n^2) complexity here?
The second loop runs n steps. Each step takes only constant time (evaluating the if statement) except for one step. The i-th step takes O(n) because the third loop is executed. So the second loop takes 2n = O(n) in total. So in total you get O(n^2).

Complexity of two imbricated loops

I have this algorithm (in c code for convenience):
int algo(int *T, int size)
{
int n = 0;
for (int i = 1; i < size; i++) {
for (int j = i; j < size; j++) {
n += (T[i] * T[j]);
}
}
return n;
}
What is this algorithm's time complexity?
My bet is it is n * log (n) since we have two imbricated iterations on the size length one time, and onsize - i the second time, but I am not sure.
A formal proof of the complexity is welcome!
This is an O(N2) algorithm.
First iteration of the outer loop runs N-1 times
Second iteration of the outer loop runs N-2 times
Third iteration of the outer loop runs N-3 times
...
Last iteration of the outer loop runs 1 time
The total number of times is (N)+(N-1)+(N-2)+...+1, which is the sum of arithmetic progression. The formula for computing the sum is N*(N-1)/2, which is O(N2).

Time complexity analysis inconsistency

I have this code :
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;
}
The time complexity of this code can be thought of as O(n) because O(n+n/2+n/4+...) = O(n)
By that logic, the time complexity of this snippet can also be argued to be O(n) :
for(i = 1; i < n; i *= 2)
//O(1) statements
Since O(1+2+4+..+n/4+n/2) = O(n). But since the loop runs log(n) times, it can be log(n) too.
Why is the former one not : log(n) times the outer loop * log(n) times the inner loop so, log(n)log(n)
What am I doing wrong ?
The first snippet has the outer loop that executes O(log n) times, and each iteration the inner loop executes O(i) times. If you sum any number of terms of the form n / 2^k, you'll get O(n).
The second piece of code has O(log n) iterations of O(1) operations, and sum of logarithmic amount of constants is still logarithmic.
In the first example, you don't have an O(1) statement inside your loop, as you have for (int j = 0; j < i; j++) count += 1. If in your second example you put the same inner loop of the first example, you are back to the same complexity. The first loop is not O(n*log(n)); this is easy to demonstrate because you can find an upper bound in O(2n) which is equivalent to O(n).
The time complexity of the 2nd one should not be calculated as a series O(1+2+4+..+n/4+n/2) = O(n), because it is not that series.
Notice the first one. It is being calculated as a series because one counts the number of times the inner for loop executes and then add all of them (series) to get the final time complexity.
When i=n inner for loop executes n times
When i=(n/2) inner for loop executes n/2 times
When i=(n/4) inner for loop executes n/4 times
and so on..
But in the second one, there is no series to add. It just comes to a formula (2^x) = n, which evaluates to x = logn.
(2^x) = n this formula can be obtained by noticing that i starts with 1, and when it becomes 2 it is multiplied by 2 until it reaches n.
So one needs to find out how many times 2 needs to be multiplied by 2 to reach n.
Thus the formula (2^x) = n, and then solve for x.

Resources