Big Oh of interesting nested loop - how to count it? - loops

I know there is many similar questions about the Big Oh notation, but this example is quite interesting and not trivial:
int sum = 0;
for (int i = 1; i <= N; i = i*2)
for (int j = 0; j < i; j++)
sum++;
The outer loop will iterate lg(N) times, but what with inner loop? And what is T(N) for all the operations?
I can see only 3 posibilities :
T(N) = lg(N) * 2^N
T(N) = log(N) * (N-1)
T(N) = N
My opinion - T(N) = N - but it is just my intuition from observations value of sum variable when N was multiplied many times - sum was almost equal to 2N, which gives us N.
Basically I do not know how to count it. Please help me with this task and explain the solution - it is quite important for me.
Thanks

The inner loop iterates the last time max. N. Before the last run it iterates N/2. If you sum it up N + N/2 + N/4 + N/8 This add up to 2*N. And that's all as you counted all runs. T(N) = N

Related

What's the time complexity of this piece of code?

I'm studying for exam and I came across this piece of code and I need to find best and worst case.
A(n):
for (int i = 1; i < n; i*=2) {
for (int j = 0; j < i; j++) {
if (i == j) return; // does nothing
for (int k = n; k > 0; k--)
if (f(n))
return g(n);
}
}
whereas functions worst and best cases are:
f(n) O(n) Ω(log^7(n))
g(n) O(n^2 * log^6(n)) Ω(n^2 * log^6(n))
Worst case:
Complexity of the first loop is log(n), and the second loop depends on first but I would say that it's complexity is n. Third for loop is n. f(n) is checked in O(n) and in worst case g(n) will be executed in last iteration and it's complexity is O(n^2 * log^6(n)). So I would say that worst case is log(n) * n * n * n + n^2 * log^6(n), so it's O(n^3 * log(n)).
Other logic would be, that as second loop depends on the first one, the iterations will go 1 + 2 + 4 + 8 + 16... which is geometric series and it's value is 2^log(n) which is n. Everything under first loop would stay same, so in this case Big-O would be O(n^3)
Best case: I found that the best case would be (n^2 * log^6(n)) as it would go straight to return statement without iterating at all.
Basically, the main question is how does log(n) times executed loop affects nested n times executed loop which depends on it.
Which logic is right for worst case, and is the best case ok?

Writing down the worst-case running time O(n) of this given code?

I have been given the following code:
void sort(int a[], int n)
{
for(int i = 0; i < n - 1; i++)
for(int j = 0; j < n - i - 1; j++)
if(a[j] > a[j+1])
swap(a + j, a + j + 1);
}
I have to calculate the worst-case running time O(n) of this code.
n is 20, so I was thinking, is O(n) = 20 - 1, or is it O(n)= n-1?
Any time you see a double-nested for loop, your first reaction should be :likely O(N²).
But let's prove it.
Start with the outer loop. It will iterate n-1 times. As n gets really large, the -1 part is negligible. So the outer loop iterates pretty close to n iterations.
When i==0, the inner loop will iterate n-2 times. But again, there's not much difference between n and n-2 in terms of scale. So let's just say it iterates n times.
When i==n-2, the inner loop will iterate exactly once.
Hence, the inner loop iterates an average of n/2 times.
Hence, if(a[j] > a[j+1]) is evaluated approximately n * n/2 times. Or n²/2 times. And for Big-O notation, we only care about the largest polynomial and none of the factors in front of it. Hence, O(N²) is the running time. Best, worst, and average.

Nested loop analyzing (each loop bounds inner loop)

In my data structure lecture, I got homework about algorithms and time complexity. I could not actually find what I need to do for this.
Question : What is the time-complexity of this algorithm ?
My solution was the analyzing loop by loop, removing constant and lower order terms of each of loop itself. For this reason , there are three loops within each other. Complexity should be O(n3). Critical point is that the innermost loop is bounded dynamically.
What is the mistake on this table ( if there is ) :
int c = 0;
for (int i = 0; i < n * n; ++i)
for (int j = 0; j < n; ++j)
for (int k = 0; k < j * 2; ++k)
c = c + 1;
return c;
All answers are welcomed.
In order to compute the time complexity, you can try and evaluate the number of iterations of the innermost loop.
the loop on k evaluates a simple expression 2 * j times.
the loop on j runs n times. Hence the inner loop runs 2 * n * (n + 1) / 2, which simplifies to n * (n + 1).
the outer loop runs n * n times. Hence the inner loops runs exactly n * n * n * (n + 1) times.
Simplifying for the dominant term, the resulting time complexity is n4.
Yet a very shrewd compiler would reduce this complexity to constant time O(1) and generate code for:
return n * n * n * (n + 1);
Trying this on Godbolt's compiler explorer shows that none of the common compilers achieve this as of now, albeit clang goes to great lengths trying to optimize the code with unfathomable SIMD code.

What is the time complexity of n * n * n iterations inside a for loop?

What is the time complexity of these loops? Correct me if I am wrong.
This loop is O(n^3) because it's got (n^3)/2 + 1 iterations.
for (int i = 0; i < n * n * n; i+=2)
{
//body
}
and
This loop is O(n^3 * m^2) since it has (n^3 + 1) * (m^2 + 1) iterations. Or would this just be O(n^3) since the inner loop is not a variable n?
for (int i = 0; i < n * n * n; i+=2)
{
for (int j = 0; j < m * m; j++)
{
//Body
}
}
In the first case the time complexity is O(n^3). It captures the most significant term so you ignore the scaling factor of 1/2 and the constant +1. In the latter case it is O(n^3 * m^2) unless you treat m as a constant and not as a variable. In the Big-O notation you don't necessary need to have only a single variable to represent the size of the input data.
This loop is O(n^3) because it's got (n^3)/2 + 1 iterations.
Correct.
This loop is O(n^3 * m^2) since it has (n^3 + 1) * (m^2 + 1) iterations. Or would this just be O(n^3) since the inner loop is not a variable n?
Both are correct. It depends if you consider m a variable or a constant.
In asymptotic notations one can have more than one variables.
For the second case considering both n and m as variables the complexity will be O(n^3 * m^2). If m is treated as a constant then the complexity is O(n^3).

What is the complexity of this piece of code

I had to determinate big O complexity of this piece of code.
I thought the answer is nlogn but apparently its n. Can anyone help explain why that is so?
void funct(int n)
{
for (int i = n; i > 0; i /= 2)
for(int j = 0; j < i; j++)
printf("%d\n", j%2);
}
That's geometric progression
The first time the inner loop is executed n times.
The second time it is executed n/2 times.
etc...
So we have the sequence:
n + n/2 + n/4 + ... + 1
so the final formula is:
n*(1 - (1/2)^(log n))/(1/2)
which is equivalent to n
Look these can be solved using Double Sigma's :
Let $ represents sigma.
so this problem is :
$(i=n downto 0 by a factor of 2 )$(j=0 to i-1) 1
where 1 represent a unit cost
now for inner sigma its sum of 1 i times that is = i
now problem is
$(i=n downto 1 by a factor of 2 ) i
which is sum of i values i.e. n+n/2+n/4+...+1(when n/2^x=1 or after log(n) terms)+0
or
n*(1+1/2+.....log(n) terms)
which is a convergent Geometric progression. and the result will be n*(1 - (1/2)^(log n))/(1/2) i.e O(n)
The outer loop, as I'm sure you can see is executed log(n) times. The inner loop is executed on average log(n)/2 times. So the printf statement is executed log(n) * (log(n) / 2) times which equals n / 2. So the complexity of the code is O(n).

Resources