Time Complexity of the given nested loops - time-complexity

I have been told that the time complexity of this code is O(n),could you please explain me how is it so. The time complexity of the outer loop is log n,inner?
int fun(int n)
{
int count = 0;
for (int i = n; i > 0; i /= 2)
for (int j = 0; j < i; j++)
count += 1;
return count;
}

That's actually quite easy once you understand what the function does.
The inner loop basically adds i to count. So you can just reduce the code here to this:
int fun(int n) {
int count = 0;
for (int i = n; i > 0; i /= 2)
count += i;
return count;
}
So now what you have is it halves i and adds that half to count.
If you keep doing that you'll end up with a number close to n. If you'd do it with an infinitely accurate float representation of i and count you will actually get exactly n (though it will take you an infinite amount of steps).
For example, let's look at n=1000, these are the steps that will be taken:
i: 500 count: 500
i: 250 count: 750
i: 125 count: 875
i: 62 count: 937
i: 31 count: 968
i: 15 count: 983
i: 7 count: 990
i: 3 count: 993
i: 1 count: 994
The 6 that are missing from count in the end are rounding mistakes at i=125/2, i=31/2, i=15/2, i=7/2, i=3/3 and i=1/2.
So you can see, the complexity of that function is almost exactly n, which certainly makes it O(n).

Related

Time complexity for an intersection (worst case)

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

Big O of Nested Loop (int j = 0; j < i * i; ++j)

Question 1
for (i = 0; i < n; i++) {
for (j = 0; j < i * i ; j++){
}
}
Answer: O(n^3)
At first glance, O(n^3) made sense to me, but I remember a previous problem I did:
Question 2
for (int i = n; i > 0; i /= 2) {
for (int j = 0; j < i; j++) {
//statement
}
}
Answer: O(n)
For Question 2, the outer loop is O(log n) and the inner loop is O(2n / log n) resulting in O(n). The inner loop is O(2n / log n) because - see explanation here: Big O of Nested Loop (int j = 0; j < i; j++)
Why we don't do Question 1 like Question 2 since in Question 1, j also depends on i which means we should really be taking the average of how many iterations will occur in the inner loop (as we do in Question 2).
My answer would be: O(n) for the outer loop and O(n^2 / n) for the inner loop which results in O(n^2) for Question 1.
Your answer is wrong. The code is Θ(n³).
To see that note that the inner loop takes i² steps which is at most n² but for half of the outer loop iterations is at least (n/2)² = n²/4.
Therefore the number of total inner iterations is at most n * n² = n³ but at least n/2 * n²/4 = n³/8.
Your consideration is wrong in that the inner loop takes on average proportional to n² many iterations, not n² / n.
What your inner for loop is doing, in combination with the outer for loop, is calculating the sum of i^2. If you write it out you are adding the following terms:
1 + 4 + 9 + 16 + ...
The result of that is (2n^3+3n^2+n)/6. If you want to calculate the average of the number of iterations of the inner for loop, you divide it by n as this is the number of iterations of the outer for loop. So you get (2n^2+3n+1)/6, in terms of Big O notation this will be O(n^2). And having that gives you... nothing. You have not gain any new information as you already knew the complexity of the inner for loop is O(n^2). Having O(n^2) running n times gives you O(n^3) of total complexity, that you already knew...
So, you can calculate the average number of iterations of the inner for loop, but you will not gain any new information. There were no cuts in the number of iteration steps as there were in your previous question (the i /= 2 stuff).
void fun(int n, int k)
{
for (int i=1; i<=n; i++)
{
int p = pow(i, k);
for (int j=1; j<=p; j++)
{
// Some O(1) work
}
}
}
Time complexity of above function can be written as 1k + 2k + 3k + … n1k.
In your case k = 2
Sum = 12 + 22 + 32 + ... n12.
= n(n+1)(2n+1)/6
= n3/3 + n2/2 + n/6

TWIN PRIMES BETWEEN 2 VALUES wrong results

I've been working on this program to count how many twin primes between two values and it's been specified that twin primes come in the (6n-1, 6n+1) format, with the exception of (3, 5). My code seems to work fine, but it keeps giving me the wrong result....1 less couple of twin primes than i should get. Between 1 and 40, we should have 5 twin primes, but I'm always getting 4. é
What am I doing wrong? Am I not taking into account (3, 5)?
Here's my code:
#include <stdio.h>
int prime (int num) {
int div;
if (num == 2) return 1;
if (num % 2 == 0) return 0;
div = 3;
while (div*div <= num && num%div != 0)
div = div + 2;
if (num%div == 0)
return 0;
else
return 1;
}
int main(void) {
int low, high, i, count, n, m;
printf("Please enter the values for the lower and upper limits of the interval\n");
scanf("%d%d", &low, &high);
printf("THIS IS THE LOW %d\n AND THIS IS THE HIGH %d\n", low, high);
i = low;
count = 0;
while (6*i-1>=low && 6*i+1<=high) {
n = 6*i-1;
m = 6*i+1;
if (prime(n) && prime(m)) ++count;
i = i + 1;
}
printf("Number of twin primes is %d\n", count);
return 0;
}
Your program misses (3 5) because 3 is not trapped as a prime number, and because 4 is not a multiple of 6. Rather than the main loop stepping by (effectively) 6, this answer steps by 1.
#include <stdio.h>
int prime (int num) {
int div;
if (num == 1) return 0; // excluded 1
if (num == 2 || num == 3) return 1; // included 3 too
if (num % 2 == 0) return 0;
div = 3;
while (div*div <= num) {
if (num % div == 0) // moved to within loop
return 0;
div += 2;
}
return 1;
}
int main(void) {
int low, high, i, count, n, m;
printf("Please enter the values for the lower and upper limits of the interval\n");
scanf("%d%d", &low, &high);
printf("THIS IS THE LOW %d\n AND THIS IS THE HIGH %d\n", low, high);
count = 0;
for (i=low; i<=high; i++) {
n = i-1;
m = i+1;
if (prime(n) && prime(m)) {
printf ("%2d %2d\n", n, m);
++count;
}
}
printf("Number of twin primes is %d\n", count);
return 0;
}
Program output
1
40
THIS IS THE LOW 1
AND THIS IS THE HIGH 40
3 5
5 7
11 13
17 19
29 31
Number of twin primes is 5
Next run:
3
10
THIS IS THE LOW 3
AND THIS IS THE HIGH 10
3 5
5 7
Number of twin primes is 2
https://primes.utm.edu/lists/small/100ktwins.txt
The five twin primes under forty are (3,5), (5,7), (11,13), (17,19), (29,31) so if you know that your code isn't counting (3,5) then it is working correctly, counting (5,7), (11,13), (17,19), and (29,31).
A possible fix would be to add an if-statement which adds 1 to "count" if the starting number is less than 4. I'm not really that used to reading C syntax so I had trouble getting my head around your formulas, sorry.
edit: since comments don't format code snippets:
i = low;
count = 0;
if (low <= 3 && high >= 3){
count ++; // accounts for (3,5) twin primes if the range includes 3
}
You have a problem in your prime function, this is the output of your prime function for the first ten prime evaluations
for(i=1;i<=10;i++) printf("%d\t%d",i,prime(i));
1 1
2 1
3 0
4 0
5 1
6 0
7 1
8 0
Note the prime() function from Weather Vane, you should include 3 as prime (and exclude 1).
From [1], twin primes are the ones that have a prime gap of two, differing by two from another prime.
Examples are (3,5) , (5,7), (11,13). The format (6n-1,6n+1) is true but for (3,5) as you stated. Your program runs almost ok since it shows the number of twin primes that are in the interval AND follows the rule mentioned above. This doesn't include (3,5). You can make a kind of exception (like if low<=3 add 1 to total count), or use another algorithm to count twin primes (like verify if i is prime, then count distance from i to next prime, if distance=2 then they are twin primes)
[1] http://en.wikipedia.org/wiki/Twin_prime

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