Can you find the time complexity of this piece of code? - time-complexity

I have tried to find but my answer doesn't match with the solution in the text.
Could anyone explain me to find the time complexity?
for (int i=0; i<n; i++)
for (int j=i; j< i*i; j++)
if (j%i == 0)
{
for (int k=0; k<j; k++)
printf("*");
}

Let f(n) be the number of operations aggregated from the outer loop,
Let g(n) be the number of operations aggregated at the level of the first inner loop.
Let h(n) be the number of operations performed at the level of the third (most inner) loop.
Looking at the most inner loop
for (int k=0; k<j; k++)
printf("*");
We can say that h(j) = j.
Now, as j varies from i to i*i, the following values of i satisfy i%j = 0, i.e. i is a multiple of j:
j = 1.i
j = 2.i
j = 3.i
...
j = (i-1).i
So
g(i) = sum(j=i, j<i^2, h(j) if j%i=0, else 0)
= h(i) + h(2.i) + ... + h((i-1).i)
= i + 2.i + ... + (i-1).i
= i.(1 + 2 + ... + i-1) = i.i.(i-1)/2
= 0.5i^3 // dropped the term -0.5i^2 dominated by i^3 as i -> +Inf
=> f(n) = sum(i=0, i<n, g(i))
= sum(i=0, i<n, 0.5i^3)
<= sum(i=0, i<n, 0.5n^3)
<= 0.5n^4
=> f(n) = O(n^4)

Could anyone explain me how to find the time complexity?
A posted claim of cited O( N^5 ) was not supported by experimental data.
Best start with experimentation on low scale:
for ( int aScaleOfBigO_N = 1;
aScaleOfBigO_N < 2147483646;
aScaleOfBigO_N *= 2
){
printf( "START: running experiment for a scale of N( %d ) produces this:\n",
aScaleOfBigO_N
);
int letsAlsoExplicitlyCountTheVisits = 0;
for ( int i = 0; i < aScaleOfBigO_N; i++ )
for ( int j = i; j < i*i; j++ )
if ( j % i == 0 )
{
for ( int k = 0; k < j; k++ )
{
// printf( "*" ); // avoid devastating UI
letsAlsoExplicitlyCountTheVisits++;
}
}
printf( " END: running experiment visits this many( %d ) times the code\n",
letsAlsoExplicitlyCountTheVisits
);
}
Having collected some reasonably large amount of datapoints ( N, countedVisits ), your next step may be to fit the observed datapoints and formulate the best matching O( f(N) ) function of N.
That can go this simple.
START: running experiment for a scale of N( 1 )
END: running experiment visits this many( 0 ) times the code.
START: running experiment for a scale of N( 2 )
END: running experiment visits this many( 0 ) times the code.
START: running experiment for a scale of N( 4 )
END: running experiment visits this many( 11 ) times the code.
START: running experiment for a scale of N( 8 )
END: running experiment visits this many( 322 ) times the code.
START: running experiment for a scale of N( 16 )
END: running experiment visits this many( 6580 ) times the code.
START: running experiment for a scale of N( 32 )
END: running experiment visits this many( 117800 ) times the code.
START: running experiment for a scale of N( 64 )
END: running experiment visits this many( 1989456 ) times the code.
START: running experiment for a scale of N( 128 )
END: running experiment visits this many( 32686752 ) times the code.
START: running experiment for a scale of N( 256 )
END: running experiment visits this many( 529904960 ) times the code.
START: running experiment for a scale of N( 512 )
END: running experiment visits this many( 8534108800 ) times the code.
START: running experiment for a scale of N( 1024 )
END: running experiment visits this many(136991954176 ) times the code.
START: running experiment for a scale of N( 2048 )
...
Experimental data show about this algorithm time-complexity behaviour in-vivo:

Related

Time complexity of below pseudocode

void buzz(int num, int [] a)
{
for(int i=1;i<num;i*=2){
for(int j=0;j<a[i]%num;j++){
print(num);
}
}
}
I understand that the outer for loop runs for log n times. Need help in understanding the complexity of the inner loop and the overall.
Let us assume num = 2^n for simplicity.
The inner loop runs a[i] % num times, which is comprised in range [0, num-1]. The outer loop runs n times so you can conclude O(num.log(num)) = O(n.2^n) worst-case complexity.
For a precise evaluation, let r[i] := a[i] % num. Then the number of print's is
r[1] + r[2] + r[4] + r[8] + ... r[2^(n-1)].
This is n times the average r (for the relevant indexes; the expectation of r could be (num-1)/2)).

Time complexity of this code?

So these are the for loops that I have to find the time complexity, but I am not really clearly understood how to calculate.
for (int i = n; i > 1; i /= 3) {
for (int j = 0; j < n; j += 2) {
... ...
}
for (int k = 2; k < n; k = (k * k) {
...
}
}
For the first line, (int i = n; i > 1; i /= 3), keeps diving i by 3 and if i is less than 1 then the loop stops there, right?
But what is the time complexity of that? I think it is n, but I am not really sure. The reason why I am thinking it is n is, if I assume that n is 30 then i will be like 30, 10, 3, 1 then the loop stops. It runs n times, doesn't it?
And for the last for loop, I think its time complexity is also n because what it does is
k starts as 2 and keeps multiplying itself to itself until k is greater than n.
So if n is 20, k will be like 2, 4, 16 then stop. It runs n times too.
I don't really think I am understanding this kind of questions because time complexity can be log(n) or n^2 or etc but all I see is n.
I don't really know when it comes to log or square. Or anything else.
Every for loop runs n times, I think. How can log or square be involved?
Can anyone help me understanding this? Please.
If you want to calculate the time complexity of an algorithm, go through this post here: How to find time complexity of an algorithm
That said, the way you're thinking about algorithm complexity is small and linear. It helps to think about it in orders of magnitude, then plot it that way. If you take:
x, z = 0
for (int i = n; i > 1; i /= 3) {
for (int j = 0; j < n; j += 2) {
x = x + 1
}
for (int k = 2; k < n; k = (k * k) {
z = z + 1
}
}
and plot x and z on a graph where n goes from 1 -> 10 -> 100 -> 1000 -> 10^15 or so, you'll get an answer which looks like an n^2 graph. When analyzing algorithmic complexity you're primarily interested in maximum the number of times, in either the worst or most common case, your inputs are looped through omitting constants. So in this case I would expect your algorithm to be O(n^2)
For further reading, I suggest https://en.wikipedia.org/wiki/Introduction_to_Algorithms ; it's not exactly easy but covers this in depth.

Time Complexity: O(logN) or O(N)?

I thought the time complexity of the following code is O(log N), but the answer says it's O(N). I wonder why:
int count = 0;
for (int i = N; i > 0; i /= 2) {
for (int j = 0; j < i; j++) {
count += 1;
}
}
For the inners for-loop, it runs for this many times:
N + N/2 + N/4 ...
it seems to be logN to me. Please help me understand why here. Thanks
1, 1/2, 1/4, 1/8... 1/2 ** n is a geometric sequence with a = 1, r = 1/2 (a is the first term, and r is the common ratio).
Its sum can be calculated using the following formula:
In this case, the limit of the sum is 2, so:
n + n/2 + n/4 ... = n(1 + 1/2 + 1/4...) -> n * 2
Thus the complicity is O(N)
Proceeding step by step, based on the code fragment, we obtain:

How to optimize code for finding Amicable Pairs

Please see the code I've used to find what I believe are all Amicable Pairs (n, m), n < m, 2 <= n <= 65 million. My code: http://tutoree7.pastebin.com/wKvMAWpT. The found pairs: http://tutoree7.pastebin.com/dpEc0RbZ.
I'm finding that each additional million now takes 24 minutes on my laptop. I'm hoping there are substantial numbers of n that can be filtered out in advance. This comes close, but no cigar: odd n that don't end in '5'. There is only one counterexample pair so far, but that's one too many: (34765731, 36939357). That as a filter would filter out 40% of all n.
I'm hoping for some ideas, not necessarily the Python code for implementing them.
Here is a nice article that summarizes all optimization techniques for finding amicable pairs
with sample C++ code
It finds all amicable numbers up to 10^9 in less than a second.
#include<stdio.h>
#include<stdlib.h>
int sumOfFactors(int );
int main(){
int x, y, start, end;
printf("Enter start of the range:\n");
scanf("%d", &start);
printf("Enter end of the range:\n");
scanf("%d", &end);
for(x = start;x <= end;x++){
for(y=end; y>= start;y--){
if(x == sumOfFactors(y) && y == sumOfFactors(x) && x != y){
printf("The numbers %d and %d are Amicable pair\n", x,y);
}
}
}
return 0;
}
int sumOfFactors(int x){
int sum = 1, i, j;
for(j=2;j <= x/2;j++){
if(x % j == 0)
sum += j;
}
return sum;
}
def findSumOfFactors(n):
sum = 1
for i in range(2, int(n / 2) + 1):
if n % i == 0:
sum += i
return sum
start = int(input())
end = int(input())
for i in range(start, end + 1):
for j in range(end, start + 1, -1):
if i is not j and findSumOfFactors(i) == j and findSumOfFactors(j) == i and j>1:
print(i, j)

Making change using Objective-C

I just recently started studying Objective-C (or programming for that matter) and am stuck at a simple program.
I'm trying to create change in quarters, dimes, nickels, and pennies but noticed that the solution I came up with would give random value to nickels or pennies.
Ex.
Change for 25 would come out to "The change is 1 quarter, 0 dime, -1881139893 nickels, and 4096 pennis"
Ex2.
Change for 30 would come out to "The change is 1 quarter, 0 dime, 1 nickels, and 4096 pennis"
What can I add/change to fix this behavior?
Also, is there any better solution then having to run 4 different if statements?
Thanks!
Here's my code below:
int orig, q, d, n, p;
NSLog(#"Give money to make change");
scanf("%i", &orig);
if(orig >= 25) {
q = orig/25;
orig -= q*25;
}
if(orig >= 10 && orig < 25) {
d = orig/10;
orig -= d*10;
}
if(orig >= 5 && orig < 10) {
n = orig/5;
orig -= n*5;
}
if(orig >= 1 && orig < 5) {
p = orig;
}
NSLog(#"The change is %i quarter, %i dime, %i nickels, and %i pennis", q, d, n, p);
You don't initialize your variables to start with, so they all start with random values, then in your code, in the case where there's no pennys, you never set p to anything, so it retains its initial random value, which you then see in your output. You can fix it by initializing your variables at the start.
int orig=0, q=0, d=0, n=0, p=0;
You should make use of modulus instead. I don't want to ruin your learning experience so this is an example of how you can use modulus to calculate days, hours, minutes and seconds for time given in seconds only.
int x = 1123123;
int seconds = x % 60;
x /= 60;
int minutes = x % 60;
x /= 60;
int hours = x % 24;
x /= 24;
int days = x;
Now apply it to your problem :)