Big O Run Time for nested loops? - performance

How do you calculate the big O run-time efficiency for this code? My gut tells me it is O(n^3) but I'm not sure, as I'm not really sure if the loops are independent or dependent.
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
for (k=1; k<=n; k++)
print ("%d %d %d/n", i, j, k);

Your gut feeling is right. You have three nested for loops iterating over n, so for each of the first n loops you make another n loops, each of which in turn make n more loops. Thus O(n^3).
Edit: think about how this will play out-
i is first 1, j 1 as well, and then k loops 1 through n. Only after k has undergone that whole loop, will j increment to 2, then k undergoes the loop once again and so on.

Yes, this function would be O(N^3) because inside each loop you are running N iterations.
The loops are not independent, because they are nested.
N * N * N = N^3

Related

What is the complexity(Ø) of this pseudo code?

My question is about finding the complexity of this algorithm. J value is related to n, so I'm confused about this.
What is the asymptotic complexity of this pseudocode?
for i=1 to n
do
j = 1;
while (j < n)
do
j = j * 2;
Thanks.
I believe it is O(n log2n)
The outer loop is called n times and the inner loop is called log2n times, since in every iteration, j is doubled. For first iteration, i.e., k=0; j is equal to 1 and goes on like 2, 4, 8, ... until 2k>=n
If I add a print at the end of the inner loop, I see:
(1,2,5)
(1,4,5)
(1,8,5)
(2,2,5)
(2,4,5)
(2,8,5)
(3,2,5)
(3,4,5)
(3,8,5)
(4,2,5)
(4,4,5)
(4,8,5)
(5,2,5)
(5,4,5)
(5,8,5)
So it appears O(n^2) but the inner loop appears constant so probably O(n) -- If the (j < n) part is switched to (j < i), that would be closer to O(n log(n)):
(2,2,5)
(3,2,5)
(3,4,5)
(4,2,5)
(4,4,5)
(5,2,5)
(5,4,5)
(5,8,5)

Complexity of a nested for loop over n and an exact integer?

I am wondering how one would find the Big-Oh complexity of an algorithm if the for loops loop over both n and some specified integer. For example, what would be the complexity of a function such as this one:
for (int i=0; i < n; i++) {
for (int j=0; j < 100; j++) {
for (int k=0; k < n; k++) {
// Some O(1) operation here.
}
}
}
Now, I know that both the outer and most-inner for loops have complexity O(n), but what is the complexity of the middle loop? O(100), would that reduce to O(1)?
Yes it will be O(1) for the middle one only. That means no matter what my input n is it doesn't matter it will run 100 times. You can't make it loop more.
But the outermost and inner most they are dependent on n. If n is 100 then ouermost runs 100 times if it is 1000000 then yes it runs 1000000 times.
What about inner most loop. For each iteration of outermost it runs 100*n times. So in total it will run even more 100*n*n times.
Now think how much total work they do?
100n^2+100n+n = An^2+B
O(n^2) will be the time complexity.
Is O(10) or O(100) and O(100000) same?
Okay I will save you from writing more for any Constant C O(C) is equivalent to O(1).
Here C was 10 or 100 or 100000.

how i can find the time complexity of the above code

for(i=0; i<n; i++) // time complexity n+1
{
k=1; // time complexity n
while(k<=n) // time complexity n*(n+1)
{
for(j=0; j<k; j++) // time complexity ??
printf("the sum of %d and %d is: %d\n",j,k,j+k); time complexity ??
k++;
}
What is the time complexity of the above code? I stuck in the second (for) and i don't know how to find the time complexity because j is less than k and not less than n.
I always having problems related to time complexity, do you guys got some good article on it?
especially about the step count and loops.
From the question :
because j is less than k and not less than n.
This is just plain wrong, and I guess that's the assumption that got you stuck. We know what values k can take. In your code, it ranges from 1 to n (included). Thus, if j is less than k, it is also less than n.
From the comments :
i know the the only input is n but in the second for depends on k an not in n .
If a variable depends on anything, it's on the input. j depends on k that itself depends on n, which means j depends on n.
However, this is not enough to deduce the complexity. In the end, what you need to know is how many times printf is called.
The outer for loop is executed n times no matter what. We can factor this out.
The number of executions of the inner for loop depends on k, which is modified within the while loop. We know k takes every value from 1 to n exactly once. That means the inner for loop will first be executed once, then twice, then three times and so on, up until n times.
Thus, discarding the outer for loop, printf is called 1+2+3+...+n times. That sum is very well known and easy to calculate : 1+2+3+...+n = n*(n+1)/2 = (n^2 + n)/2.
Finally, the total number of calls to printf is n * (n^2 + n)/2 = n^3/2 + n^2/2 = O(n^3). That's your time complexity.
A final note about this kind of codes. Once you see the same patterns a few times, you quickly start to recognize the kind of complexity involved. Then, when you see that kind of nested loops with dependent variables, you immediately know that the complexity for each loop is linear.
For instance, in the following, f is called n*(n+1)*(n+2)/6 = O(n^3) times.
for (i = 1; i <= n; ++i) {
for (j = 1; j <= i; ++j) {
for (k = 1; k <= j; ++k) {
f();
}
}
}
First, simplify the code to show the main loops. So, we have a structure of:
for(int i = 0; i < n; i++) {
for(int k = 1; k <= n; k++) {
for(int j = 0; j < k; j++) {
}
}
}
The outer-loops run n * n times but there's not much you can do with this information because the complexity of the inner-loop changes based on which iteration of the outer-loop you're on, so it's not as simple as calculating the number of times the outer loops run and multiplying by some other value.
Instead, I would find it easier to start with the inner-loop, and then add the outer-loops from the inner-most to outer-most.
The complexity of the inner-most loop is k.
With the middle loop, it's the sum of k (the complexity above) where k = 1 to n. So 1 + 2 + ... + n = (n^2 + n) / 2.
With the outer loop, it's done n times so another multiplication by n. So n * (n^2 + n) / 2.
After simplifying, we get a total of O(n^3)
The time complexity for the above code is : n x n x n = n^3 + 1+ 1 = n^3 + 2 for the 3 loops plus the two constants. Since n^3 carries the heaviest growing rate the constant values can be ignored, so the Time complexity would be n^3.
Note: Take each loop as (n) and to obtained the total time, multiple the (n) values in each loop.
Hope this will help !

What is the Big O of such an algorithm?

If you had code that looks like this, what would the big O be? I'm uncertain as to how if statements affect big O.
n = some arbitrary number
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if(i <= j)
for(k = i; k <= j; k++)
//do some simple operation
y = x+1
else
//do some simple operation
y = y+1
I'm not considering compiler optimizations. I know this is somewhere between O(n^2) and O(n^3) but am not sure as the if statement does not always execute the inner most loop.
O(N * N * N) which we can just say is O(N^3)
First Loop happens N times.
Second Loop happens N times.
Those multiply together to get O(N^2)
Out of all the possible N^2 loops, the third loop would run about half the time, which is O(N/2) which is equivalent to O(N).
And that's how you get O(N * N * N) or O(N^3)
In fact you can count (almost exactly) how many operations you do:
i: 0 to n-1 = N operations
x
j: 0 to n-1 = N operations
x
only when i<=j, from i to j, or another task O(1)
The other task gives you NxN operations, then O(NxN)
that is, if you invert
for every j (0 to n-1) : N operations
then for every i from 0 to j, you do an operation from i to j, that is j-i+1
exactly the same as every 0 to j operations. Then you have (j+1)x(j+2)/2 operations.
then finally, you get Sum (j+1)x(j+2)/2 from 0 to N which is
1/2 ((N+1)x(N+2)/2 + (N+1)^3/3+(N+1)^2/2+(N+1)/6) operations, so O(N^3)
Perhaps, I forgot some +/-1
You can analyse your algorithm using Sigma notation:
From this, it's obvious the time complexity will depend on cubic n terms, and hence your algorithm is in O(n^3).
This is O(N^3).
Proof: http://www.wolframalpha.com/input/?i=sum+sum+%28j+-+i+%2B+1%29%2C+j+%3D+i+to+n+-+1%2C+i+%3D+0+to+n+-+1
Last cycle runs (j - i + 1) times.
How to find this sum manually?
This is not a rocket math.
Try to read about https://en.wikipedia.org/wiki/Telescoping_series
Just to save time it's easier to use wolframalpha for that purpose.

The relation between double loops and number of operations

My teacher told me that basically whenever we had a loop and a nested loop the number of operation was as follows n(n+1)/2.
However, I looked at some programs and I realized that it's unlikely to be the case.
for(i=0, i<n, n++)
for(j=i, j<n, j++)
{x=i+j}
in this case it would be n(n+1)/2, ignoring i=0, j=0, n++, j++ and x=i+j, but here:
for(i=0, i<n, n++)
for(j=0, j<n, j++)
{x=i+j}
it would be n^n unless i am mistaken.
Can someone tell me exactly when two loops have n(n+1)/2 number of operations? I am kinda confused right now.
In your first example, the operation would be done n times, then n-1 times, then n-2 times. If I remember correctly, this is n(n-1)/2, but you could be right and it's n(n+1)/2. Either way, it's a very small difference.
In your second example, it would be done n times, then n times, then n times... until you've done it n times n times -- in other words, n^2.
You probably misunderstood the teacher (or the teacher made a mistake). n(n-1)/2 is just one example of a common loop runtime. It can be anything as you've observed. Your second example has n^2 operations though, another common pattern. 'n^n' is much rarer.
for(i=0, i<n, n++)
for(j=0, j<n, j++)
{x=i+j}
First loop runs n times and for each iteration you run second loop n times, thus you have n*n = n^2.
for(i=0, i<n, n++)
for(j=i, j<n, j++)
{x=i+j}
First loop runs n times and for each iteration you run the second loop (n-i) times....thus number of times x=i+j is getting executed is 1 + 2 + 3 ..... + n times, this sequence is sum of first n integers, which is same as n(n+1)/2

Resources