Complexity of a code fragment - algorithm

for(int i = 0; i < N; i++)
if(i < 2 || i > N - 3)
for(int j = 1; j <= 10N; j++)
a[i] = a[j - 1] / 2;
So the answer is N(1 + 10N(1)) = n + 10n^2 right? or is it n?
Please explain.

This looks O(N) to me.
The if statement is true for i = 0,1,N-1,N-2, which is a constant number of cases.

Your conclusion is wrong. Although the outer for loops N times, the if condition is only true in 4 cases (0, 1, N-2, N-1). So the total run time is rather N + 4·10·N that is in O(n).

If you want an asymptotic upper bound... O(n^2). If you want to be pickier than that, we need to define computational weights for individual instructions.
Edit: Yeah, it's O(n). I read it wrong the first time.

Related

Time complexity of nested while with changing condition

I'm trying to solve the complexity of this loop
for(int i= 0; i < n; i++) {
c = i;
while(c > 1){
O(1);
c = c / 2;
}
}
as the while condition changes in every loop I don't know how to calculate that strange series.
I mean, if the loop where
for(int i= 0; i < n; i++) {
c = n;
while(c > 1){
O(1);
c = c / 2;
}
}
I know the while has a complexity of O(logn) and it repeats itself n times, so the complexity would be O(nlogn).
The problem I have with previous loop is "c=i". As c=i, first time (c=0) the loop would reproduce 0 times, when c=1 it would reproduce 0 times again, when c=2 it would reproduce 1 time, then the series would follow and it is 0, 0, 1, 2, 2, 3, 3... (while reproductions each time of for loop)
O(logn) would not repeat itself n times, would repeat a number of times I can't come up with, so I don't know how to solve it.
This need a bit of math involved.Given that log is well defined for a and b:
log(a) + log(b) = log(ab)
Here you have
log(1) + log(2) +....+ log(n) = log(1*....*n) = log(n!)
There is a mathematical approximation for log(n!), namely
log(n!) ~ nlog(n) - n + 1
which reveal O(log(n!)= O(nlog(n))

Theta Runtime of a triple loop that essentially much less than n^3

I was looking at a programming question today and I had an issues finding the theta runtime of it. Basically, within my question, I form the following loop structure:
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
for(int k = j + 1; k < n; k++)
//check some condition
By obvious inspection, it is O(n^3). More accurately, it is o(n^3). However, I want to know what the theta runtime of this is. If you examine this loop, the actual amount of times the inner condition executes is n!/3!(n-3)! since it is evaluating all combinations of n numbers without repetition.
Is there a way to express the theta runtime in polynomial form other than n choose r?
For example, the runtime of selection sort (similar but with only 2 for loops) can be evaluated by looking at the number of instructions being executed. n + (n-1) + (n-2) ... + 1 would simplify to n(n+1) / 2.
n!/3!(n-3)! = n(n-1)(n-2)/3! = (n^2-n)(n-2)/6 = (n^3-2n^2-n^2+2n)/6
= (n^3 -3n^2 + 2n)/6
You can show easily1 that for large enough values of n:
1/2 n^3 < (n^3 -3n^2 + 2n)/6 < 2n^3
So when it comes to asymptotic notation, it is in Theta(n^3), and NOT in o(n^3).
(1) One way to show it is:
lim 1/2n^3 / ((n^3 -3n^2 + 2n)/6) when n->infinity = 1/2 < infinity
And similarly for the other inequality

Algorithmic order of growth of the code

I am attending a course online and stuck at the following question. What is the order of growth of the worst case running time of the following code fragment as a function of N?
int sum = 0;
for (int i = 1; i <= N*N; i++)
for (int j = 1; j <= i; j++)
for (int k = 1; k <= j; k++)
sum++;
I thought that it is of the order of N^4 but it seems this answer is wrong. can you please explain?
It is of order O(N^6). You should note that it is not true that every loop simply add an order N to the complexity. Considering the following example:
int sum = 0;
for (int i = 1; i <= M; i++)
for (int j = 1; j <= i; j++)
for (int k = 1; k <= j; k++)
sum++;
You should be able to figure out it is of order O(M^3) easily, so if you replace M=N^2, then you will get the answer. The key point is that every inner loop are of order O(N^2) in this case, but not O(N).
Let's denote n = N^2. Then, the loop will execute each time that k <= i <= j. This will be approximately n^3/6 times. Thus, the runtime is O(n^3)= O(N^6)
Explanation: Ignoring for a moment the cases where k==i or j==i or j==k,
we take 1 out of 6 distinct triples :
(a1,a2,a3)
(a1,a3,a2)
(a2,a1,a3)
(a2,a3,a1)
(a3,a2,a1)
(a3,a1,a2)
Overall, there are n^3 triples. Only one out of 6 triples obeys the order.
One run of the inner loop increments sum exactly j times.
One run of the middle loop invokes the inner loop exactly i times, with values of j between 1 and i (inclusive). So it increments sum exactly 1+2+3+...i times, which is i.(i+1)/2 by the well-known "triangular numbers" formula.
The outer loop invokes the middle loop exactly N^2 times (let us denote it as M), with values of i between 1 and M (inclusive). So it increments sum exactly 1+3+6+...M.(M+1)/2 times. Similarly, this is M.(M+1).(M+2)/6, by the not-so-well-known "tetrahedral numbers" formula (http://en.wikipedia.org/wiki/Tetrahedral_number).
All in all, the final value of sum is N^2.(N^2+1).(N^2+2)/6.
Thinking in asymptotic terms, the inner loop is O(j), the middle one O(i^2) (by summation) and the outer one O(M^3) (by summation), i.e. O(N^6).
Also see Faulhaber's formula, which shows that the sum of n^k is O(N^(k+1)) (http://en.wikipedia.org/wiki/Faulhaber%27s_formula).
Any given run of the innermost (k) loop has a time proportional to j, but we've got to do one of those for each of j = 1 through j = i, and that sum 1 + 2 + … + i grows like i^2. So for any given i we've got an O(i^2) running time, but of course we've got to deal with i = 1 through i = N^2. The sum of i^2 for i = 1 through N^2 happens to grow like N^6.

Iterative function

Stuck with me HW - Need to try complexity
time=0;
for (i=n; i>=1; i = sqrt(i))
for (j=1; j<=i; j++)
time++;
What I did - First loop going like this:
i=n, n^(1/2), n^(1/4)...1
than we get:
n^(1/2)^k = 1
if I log both sides one side get 0... what should I do?
I suppose there is a typo somewhere because otherwise it's Θ(∞) if the input n is not smaller than 1. (For i == 1, the update i = sqrt(i) doesn't change i, so that's an infinite loop.)
So let us suppose it's actually
time = 0;
for (i = n; i > 1; i = sqrt(i))
for (j = 1; j <= i; j++)
time++;
Then, to get the complexity of nested loops, you need to sum the complexity of the inner loop for each iteration of the outer loop. Here, the inner loop runs i times, obviously, so we need to sum the values i runs through in the outer loop. These values are n, n^0.5, n^0.25, ..., n^(1/2^k), where k is characterised by
n^(1/2^(k+1)) < 2 <= n^(1/2^k)
or, equivalently,
2^(2^k) <= n < 2^(2^(k+1))
2^k <= lg n < 2^(k+1)
k <= lg (lg n) < k+1
k = floor(lg(lg n))
Now it remains to estimate the sum from above and below to get the Θ of the algorithm. This estimate is very easy if you start writing down the sums for a few (large) values of n.

Asymptotic analysis of three interdependent nested for loops

The code fragment I am to analyse is below:
int sum = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < i * i; j++)
for (int k = 0; k < j; k++)
sum++;
I know that the first loop is O(n) but that's about as far as I've gotten. I think that the second loop may be O(n^2) but the more I think about it the less sense it makes. Any guidance would be much appreciated.
The first loop executes n times. Each time, the value i grows. For each such i, the second loop executes i*i times. That means the second loop executes 1*1 + 2*2 + 3*3 + ... + n*n times.
This is a summation of squares, and the formula for this is well-known. Hence we have the second loop executing (n(1 + n)(1 + 2 n))/6 times.
Thus, we know that in total there will be (n(1 + n)(1 + 2 n))/6 values of j, and that for each of these the third loop will execute 1 + 2 + ... + j = j(j+1)/2 times. Actually calculating how many times the third loop executes in total would be very difficult. Luckily, all you really need is a least upper bound for the order of the function.
You know that for each of the (n(1 + n)(1 + 2 n))/6 values of j, the third loop will execute less than n(n+1)/2 times. Therefore you can say that the operation sum++ will execute less than [(n(1 + n)(1 + 2 n))/6] * [n(n+1)/2] times. After some quick mental math, that amounts to a polynomial of maximal degree 5, therefore your program is O(n^5).
int sum = 0;
for (int i = 0; i < n; i++) // Let's call this N
for (int j = 0; j < i * i; j++) // Let's call this M
for (int k = 0; k < j; k++) // Let's call this K
sum++;
N is the number of steps of the entire program, M is the number of steps the two inner loops do and lastly K is the number of steps the last loop does.
It is easy to see that K = j, it takes j steps to do.
Then M = Sum(j=0,i^2,K) = Sum(j=0, i^2, j)
(First param is the iterator, second is the upper bound and last param is what we are adding)
This is actually now a sum of n numbers to i*i. Which means we can apply the formula ((n+1)*n)/2
M = Sum(j=0,i^2,j) = ((i^2+1)*(i^2))/2 = (i^4 + i^2)/2
N = Sum(i=0, n, M) = 1/2 * ( Sum(i=0, n, (i^4)) + Sum(i=0, n, (i^2)) )
These are both well known formulas and after a little playing you get:
N = (n^5)/10 + (n^4)/4 + (n^3)/3 + (n^2)/4 + n/15
This should be the exact number of steps the loop takes, but if you are interested in the O notation you can note that n^5 is the strongest growing part so the solution is O(n^5)
If you proceed methodically using Sigma Notation, you'll end up with the following result:
Try to count how many times the inner loop is executed:
The middle loop runs
0*0 times when i == 0
1*1 times when i == 1
2*2 times when i == 2
...
n*n = n^2 times when i == n.
So it is O(n^2).

Resources