Time complexity for an intersection (worst case) - time-complexity

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.

Related

What is the complexity of this for loop, for (int j = i; j < n; j++)?

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).

Time complexity of inner for loop

I have been trying to figure out how the get to the solution of this for loop but I cant seem to understand why the answer is what it is. I get stuck on the inner for loop, can someone help me break it down step by step and to get to the answer of the second for loop, line 2. THIS IS FOR REVIEW NOT HOMEWORK. I am just trying to understand the concept better.
1: for (int i = 0; i < n; i++) { // Runs n+1 times
2: for (int j = n; j >= i; j--) { // Runs (n+2)+(n+1)+ n(n+1)/2 - 3 times
3: cout << i << “,” << j <<endl; // Runs (n+1) + n(n+1)/2 - 1 times
4: }
5: }
I know the second line is simplified to n(n+1)/2 +2n, but I dont understand how to even get the (n+2)+(n+1)+ n(n+1)/2 - 3 first.
1: for (int i = 0; i < n; i++) { // Runs n+1 times
This line does not run for n+1 times. Since it is i < n It runs for n times.
2: for (int j = n; j >= i; j--) {
This line runs for n - i + 1 times. Because it uses >= for comparison.
So if we write down the executions for cout , we get something like this:
1: n+1
2: n
3: n-1
...
...
n: 1
So what we need to do is simply add numbers up to n+1
which is (n+1)(n+2)/2
hope this helps
for (int i = 0; i < n; i++) {
for (int j = n; j >= i; j--) {
cout << "something" << endl;
}
}
Lets see for the values of i, how many times the inner loop is run.
i=0 --> n
i=1 --> n-1
i=2 --> n-2
i=3 --> n-3
...
...
i=n-1 --> 1
Let us increase each element to n to have an upper bound
1 + 2 + 3 +....+ n-1 + n < [n + n + n + .... + n] = O(n^2)
Lets throw half of the first elements, and the other half decrease it to n/2. For a lower bound.
1 + 2 + 3 +....+ n-1 + n > [n/2 + n/2 + ... + n/2] = (n/2)*(n/2) = (n^2)/4 = Ω(n^2)
Lower and Upper bounds are Ω(n), O(n), we can deduce it is actually ϴ(n).
We could have done this immediately by noticing it is actually an arithmetic sequence.
1 + 2 + 3 + ... + n = (1+n)*(n-1)/2 = ϴ(n^2)

Understanding the theoretical run time of a function with nested loops

I've been trying to understand Big-O notation. Earlier today, I was given a function to practice with and told that it has a O(n^5). I've tried calculating it on my own but don't know if I've calculated T(n) correctly.
Here are my two questions:
1) Did I calculate T(n) correctly and if not then what did I do wrong?
2) Why do we only concern ourselves with the variable to the highest power?
1 sum = 0; //1 = 1
2 for( i=0; i < n; i++) //1 + n + 2(n-1) = 1+n+2n-2 = 3n-1
3 for (j=0; j < i*i; j++) //n + n*n + 2n(n-1))= n+ n^2 + 2n^2-2n = 3n^2 -n
4 for (k=0; k < j; k++) //n + n*n + 4n(n-1))= n + n*n +4n*n-4n = 5n^2 -3n
5 sum++;
6 k++;
7 j++;
8 i++;
// so now that I have simplified everything I multiplied the equations on lines 2-4 and added line 1
// T(n) = 1 + (3n-1)(3n^2-n)(5n^2 -3n) = 45n^5 -57n^4 +23n^3 -3n^2 + 1
Innermost loop runs j times.
Second loop runs for j = 0 to i^2 -> sum of integers.
Outer loop runs to n -> sum of squares and 4th powers of integers.
We only take the highest power because as n approaches infinity, the highest power of n (or order) will always dominate, irrespective of its coefficient.

What is time complexity for the following code?

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.

Finding the big theta bound

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