It seems the complexity of the following code should be O(n^2) but it's O(n), how?
void fun(int n, int arr[])
{
int i = 0, j = 0;
for(; i < n; ++i)
while(j < n && arr[i] < arr[j])
j++;
}
In the first look, the time complexity seems to be O(n^2) due to two loops. But, please note that the variable j is not initialized for each value of variable i.
Hence, the inner j++ will be executed at most n times.
The i loop also runs n times.
So, the whole thing runs for O(n) times.
Please observe the difference between the function given in question and the below function:
void fun(int n, int arr[])
{
int i = 0, j = 0;
for(; i < n; ++i)
{
j = 0;
while(j < n && arr[i] < arr[j])
j++;
}
}`
Still not convinced ?
Let's assume the array passed has its element in decreasing order. We will just dry run through the code :
Iteration 1 : i = 0, j = 0. arr[0] < arr[0] is false. So, the
inner while loop breaks.
Iteration 2: i =1, j = 0. arr[1] < arr[0] is true. j becomes
Iteration 3 : i = 1, j = 1. Condition false. We break. Note
that j will remain 1 and is not reset back to 0.
Iteration 4 : i = 2, j = 1. arr[2] < arr[1]. True. j = 2.
Iteration 5 : i = 2, j = 2. Condition false. Break.
Iteration 6 : i = 3, j = 2. arr[3] < arr[2]. True. j = 3.
Iteration 7 : i = 3, j = 3. Condition false. Break.
As you can see, the inner while loop only runs once in this case.
So, total iterations is 2 * N.
j is not reset to 0 with every iteration of the outer loop. As such, it runs to n-1 just once, same as i does. So you have two parallel/intermingled iterations from 0 to (at most) n-1.
In every step, the program increases i by one. The program terminates when i reaches n. The "outer loop" is run n times.
There is also an "inner loop" about j. But all it does is increase j until it reaches i (at most, sometimes it does less). j is never decreased. So that part is also run at most n times in total (not n times for each iteration of the "outer loop").
The answer is O(n)
The outer loop runs 'n' times and the inner loop only runs to 'n' a single time in all the iterations combined as the value of j is never reset to 0.
Therefore the answer is O(n+n)=O(n).
Lets consider the worst case when the while loop is executed maximum no. of times.
Initially: i=0 , j=0 => while loop does not gets executed since arr[0] = arr[0] i.e. j=0.
Second iteration : i=1 , j=0 => while loop gets executed for the worst case i.e. j=1.
Third iteration : i=2 , j=1 => while loop again gets executed for the worst case i.e. j=2.
...
nth iteration : i=n-1 , j=n-2 => while loop again gets executed for the worst case i.e. j=n-1.
So, by doing this exercise we can observe that every time j = i-1
except i=0 and j=0 OR we can say that the while loop is just running in parallel to the for loop and thus the no. of executions of the while loop is equal to the no. of executions of the for loop.
Hence Order = O(n);
The answer is O(n) because the test condition inside the 'while' loop fails!
while(j < n && arr[i] < arr[j])
In the beginning, i=0 and j=0, which means arr[i] = arr[j], but the while loop test condition says arr[i]<arr[j], and its completely wrong to assume arr[0]<arr[0]
The code only runs the for loop n times.
The final answer is O(n) not O(n^2)
For some clarity, you can go through these two examples
Example 1 :
#include <stdio.h>
int main()
{
int i = 0, j = 0;
int n = 5;
int arr[] = {6,7,8,9,10,11};
for(; i < n; ++i)
{
printf("\nThis is for loop, its running 5 times\n");
while(j < n && arr[i] < arr[j]){
j++;
printf("\nThis is while loop!\n");
}
};
return 0;
}
The Output is :
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
In the above output, we can't find the print statement present in 'while' loop
Example 2 :
#include <stdio.h>
int main()
{
int i = 0, j = 0;
int n = 5;
int arr[] = {6,7,8,9,10,11};
for(; i < n; ++i)
{
printf("\nThis is for loop, its running 5 times\n");
while(j < n && arr[i] <= arr[j]){
j++;
printf("\nThis is while loop!\n");
}
};
return 0;
}
Here, a small change is made
arr[i] <= arr[j]
'=' is used
Output:
This is for loop, its running 5 times
This is while loop!
This is while loop!
This is while loop!
This is while loop!
This is while loop!
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
Here, the print statement in while loop is executed, because arr[i]=arr[j],
arr[0] = arr[0]
For the 'Example 2' shown above the time complexity is O(n^2)
Note that the variable j is not initialized for each value of variable i.
Hence, the inner j++ will be executed at most n times.
The i loop also runs n times.
So, the whole thing runs for O(n) times.
Related
Having trouble finding the time complexity for the worst-case time complexity. This case is for an intersection of two sort arrays of the same size (n).
Not sure how to count the while loop with two conditions or how to count the if and else if statements
I know the big 0 would be N+N but no idea how to show the worst case.
int printIntersection(int arr1[], int arr2[]) {
int i = 0, j = 0;
while (i < n && j < n) {
if (arr1[i] < arr2[j])
i++;
else if (arr2[j] < arr1[i])
j++;
else /* if arr1[i] == arr2[j] */ {
cout << arr2[j] << " ";
i++;
j++;
}
}
}
To prove that in the worst case the loop will make 2N iterations you can use the following argument.
Given two indices i and j at each step:
if arr1[i] < arr2[j] then i is incremented by 1
if arr2[i] > arr1[j] then j is incremented by 1
if arr2[i] = arr1[j] then both i and j are incremented by 1
At each iteration at least one between i and j is incremented by one and the maximum number of iterations is bounded by 2N (both i and j go from 0 to n-1),
you get your resulting worst case time complexity.
what is the complexity of the second for loop? would it be n-i? from my understanding a the first for loop will go n times, but the index in the second for loop is set to i instead.
//where n is the number elements in an array
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
// Some Constant time task
}
}
In all, the inner loop iterates sum(1..n) times, which is n * (n + 1) / 2, which is O(n2)
If you try to visualise this as a matrix where lines represents i and each columns represents j you'll see that this forms a triangle with the sides n
Example with n being 4
0 1 2 3
1 2 3
2 3
3
The inner loop has (on average) complexity n/2 which is O(n).
The total complexity is n*(n+1)/2 or O(n^2)
The number of steps this takes is a Triangle Number. Here's a bit of code I put together in LINQpad (yeah, sorry about answering in C#, but hopefully this is still readable):
void Main()
{
long k = 0;
// Whatever you want
const int n = 13;
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
k++;
}
}
k.Dump();
triangleNumber(n).Dump();
(((n * n) + n) / 2).Dump();
}
int triangleNumber(int number)
{
if (number == 0) return 0;
else return number + triangleNumber(number - 1);
}
All 3 print statements (.Dump() in LINQpad) produce the same answer (91 for the value of n I selected, but again you can choose whatever you want).
As others indicated, this is O(n^2). (You can also see this Q&A for more details on that).
We can see that the total iteration of the loop is n*(n+1)/2. I am assuming that you are clear with that from the above explanations.
Now let's find the asymptotic time complexity in an easy logical way.
Big Oh, comes to play when the value of n is a large number, in such cases we need not consider the dividing by 2 ( 2 is a constant) because (large number / 2) is also a large number.
This leaves us with n*(n+1).
As explained above, since n is a large number, (n+1) can be approximated to (n).
thus leaving us with (n*n).
hence the time complexity O(n^2).
How do I calculate the time complexity of the following function?
int Compute (int n)
{
int j = 0;
int i = 0;
while (i<=n)
{
i = 2*j + i + 1;
j++;
}
return j-1;
}
Now, I know that the loop has O(n) time complexity, but in this case i grows in a much faster rate. Taking this iteration by iteration I found out that, for every m-th iteration i = m^2. But I'm still confused how to calculate Big-O.
If you look at the values of i and j for a few iterations:
i=1
j=1
i=4
j=2
i=9
j=3
i=16
j=4
and so on. By mathematical induction we can prove that i takes square values: ( 2*n + n^2 + 1 = (n+1)^2 )
Since we loop only while i<=n and since i takes the vales 1, 2^2, 3^2,..., k^2 <=n, it means that we stop when i=k goes over sqrt(n). Hence the complexity seems to be O(k) which means O(sqrt(n)).
Give big theta bound for:
for (int i = 0; i < n; i++) {
if (i * i < n) {
for (int j = 0; j < n; j++) {
count++;
}
}
else {
int k = i;
while (k > 0) {
count++;
k = k / 2;
}
}
}
So here's what I think..Not sure if it's right though:
The first for loop will run for n iterations. Then the for for loop within the first for loop will run for n iterations as well, giving O(n^2).
For the else statement, the while loop will run for n iterations and the k = k/ 2 will run for logn time giving O(nlogn). So then the entire thing will look like n^2 + nlogn and by taking the bigger run time, the answer would be theta n^2 ?
I would say the result is O(nlogn) because i*i is typically not smaller than n for a linear n. The else branch will dominate.
Example:
n= 10000
after i=100 the else part will be calculated instead of the inner for loop
int main (int argc, const char * argv[]){
#autoreleasepool {
int x = 1;
for (x = 1; x <= 10; x++) {
NSLog(#"%i",x); //the answer here is 10.
}
NSLog(#"Number %i",x); //the answer here is 11.
}
return 0;
}
So my question is, why when I print 'x' outside the for loop it adds 1 to the initial 10?
thanks in advance.
The loop ends once x is greater than 10. Therefore, it goes through the loop 10 times, adds one, which is 11 and breaks out of the loop.
It's not, the loop declaration adds it.
for (x = 1; x <= 10; x++) {
// some code
}
is like
x = 1;
while(x <= 10) {
// some code
x++;
}
When x = 11, the loop stops.
Your loop is equal to
x = 1;
while(x <= 10)
{
// log x
x++;
}
As you can see, on the last iteration (x = 10) x is incremented and only then the loop breaks.
Because "for" loop first increments the value of variable x and then compares with the condition!
It because step clause x++ is run after the last successful loop iteration. That's how it knows to stop.
x = 1, then we loop 10 times, incrementing it each time.
You get to x = 10 and your loop body runs its last time.
The step clause then runs x++ and now x = 11
Check loop condition x <= 10, which is now false and the loop exits.
If x never got to 11, you would never know when to exit this loop.
The loop iterates for 10 times from 1 to 10 and when the loops ends the value of x becomes 11.