Reputation: 9
I am trying to find time complexity for this Code.
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
My Attempt: We can write this loop in the form:
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
Now Big Oh of this loop is O(n^5). Am I correct or doing some mistake?
Upvotes: 1
Views: 6655
Reputation: 53958
Now Big Oh of this loop is O(n^5). Am I correct or doing some mistake?
No, this is not correct. The time complexity is O(n^3)
.
In simple terms, you can think it off like this:
The maximum steps done in each for loop starting at 0
and reaching n-1
making steps of 1 are n
. So if you have two loops, one nested in the other then for each step you make in the outer loop you make n
steps in the nested loop. Given the steps you will make in the outer loop is n
, it's pretty evident that at the end you will make n^2
steps.
Based on the above, you can easily draw that in the following case:
for(int i=0; i<=n-1; i++)
{
for(int j=0; j<=n-1; j++)
{
for(int k=0; k<=n-1; k++)
{
}
}
}
you will make n^3
steps. So the complexity is of the order of O(n^3)
.
Upvotes: 1
Reputation: 350137
The first variant of your code with a counter added:
int count = 0
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
count++;
This counts every combination of (i, j, k) with 0 <= i < j < k < n. This corresponds to the number of ways you can pick 3 elements from n elements, without taking the order of them into account. There is a formula for that number:
n(n-1)(n-2) / 3! = n3/6 - n2/2 - n/2
The second variant:
int count = 0
for (int i = 0; i <= n - 1; i++)
for (int j = 0; j <= n - 1; j++)
for (int k = 0; k <= n - 1; k++)
count++;
... counts the number of ways you can pick 3 from n items, but where the order is important, and repetitions within the 3 selections are allowed. The number is quite easy to derive as i, j, k are independent and each can get n different values, so the total number is:
n3
Now they represent the same time complexity:
O(n3/6 - n2/2 - n/2) = O(n3)
This is because of the properties of big O:
if a function may be bounded by a polynomial in n, then as n tends to infinity, one may disregard lower-order terms of the polynomial.
And:
Multiplication by a constant
Let k be a constant. Then:
O(kg) = O(g) if k is nonzero.
Upvotes: 6
Reputation: 101
Are those loops nested? If so, you're on the right track with rewriting the loop like that to make things easier to reason about. Although I would give each loop a different iterator name than i to avoid confusion:
for (int a = 1; a <= n; a++) {
for (int b = 1; b <= n; b++) {
for (int c = 1; c <= n; c++) {
...
}
}
}
In fact you could rename these variables to whatever you want to make things easier to reason about. How about:
for (int street = 1; street <= n; street++) {
for (int house = 1; house <= n; house++) {
for (int room = 1; room <= n; room++) {
...
}
}
}
Now, the problem becomes, if I have to visit n rooms in n houses in n cities, how many rooms do I have to visit?
Hopefully you can see that the answer is n * n * n , i.e. n^3.
The shortcut way of getting to the answer is just to see you have 3 nested for loops from 1 to n, so the answer is n^3.
Upvotes: 1
Reputation: 140158
if you have a doubt and you want to convince yourself just perform a little test:
#include <stdio.h>
int main()
{
int count1=0,count2=0;
int n=100;
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
count1++;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
count2++;
printf("count1 %d count2 %d n %d\n",count1,count2,n);
return 0;
}
result:
count1 161700 count2 1000000 n 100
clearly, 2nd loop runs 100**3
times => O(n**3)
first loop runs less because of the bounds, but it's still linear (no divide operations on bounds) => O(n**3) as well even if it is faster.
Upvotes: 0