Basic Algorithm Analysis and Summation Notation - algorithm

So for a homework we had to count the number of steps in a piece of code. Here it is:
int sum = 0;
for (int i = 1; i <= n*n; i++)
for (int j = 1; j <= i; j++)
for (int k = 1; k <= 6; k++)
sum++;
My prof (i think) explained that the number of operations in the 2nd line could be found using summation notation, like so:
n^2
Σ x 4 + 3
i=1
which would be 1/2(n^4 + n^2) x 4 + 3 = 2n^4 + 2n^2 + 3
but from just looking the line, I would think it would be something like 4n^4 + 2 (my prof said 4n^4 + 3, I'm not sure where the third operation is though...)
Am I doing the summation notation wrong here? It made sense to me to do summation notation for nested for loops, but I don't know why it would work for a for loop by itself.
Thanks.

Actually even your prof result is wrong. The exact result is 3n^4+3n^2.
To obtain that result simply consider:
All passages are pretty simple (the passage from step 4 to step 5 is immediate if you consider the formula for the sum of the firsts n natural numbers).

I guess both you and your professor are wrong. According to my calculation (I might be wrong too) it should be 3n^4+3n^2.
The outer most loop will run n^2 times. Taken this into consideration the inner loop will run 1 time for the first iteration and so on till n^2. i.e. from j=1 to j=1,2,3,4 ... n^2. If we sum the series (1+2+3...n^2) this becomes (n^2(n^2+1))/2.
So for n^2 iterations of outer loop the inner loop will execute (n^2(n^2+1))/2 times. The most inner loop executes six times for every iteration of the second loop. So by just multiplying (n^2(n^2+1))/2 with 6 it evaluates to 3n^4+3n^2.
To check the answer let's take an example. Say n=5, run your algorithm and print the sum this will give 1950. Now substitute this value in the evaluated expression, this will be like 3(5^4)+3(5^2) and again this evaluates to 1950.

What you need to calculate is this:
S = sum(i in 1..n^2) sum(j in 1..i) sum(k in 1..6) 1
Now, the innermost sum is obviously 6, hence we have
S = sum(i in 1..n^2) sum(j in 1..i) 6
= 6 sum(i in 1..n^2) sum(j in 1..i) 1
The innermost sum is just the sum of the first i numbers, which you should know is i(i + 1)/2, giving
S = 6 sum(i in 1..n^2) i(i + 1)/2
= 3 sum(i in 1..n^2) i(i + 1)
= 3 sum(i in 1..n^2) (i^2 + i)
We can separate this into two sums:
S = 3 [ (sum(i in 1..n^2) i^2) + (sum(i in 1..n^2) i) ]
The second sum there is just our old friend, the sum of the first n^2 numbers, so expanding that is easy.
The first sum there is a new friend, the sum of the first n^2 squares. You can google for that if you don't know it off hand.
Drop in the formulae, expand a little, tidy with a broom, and you should get your answer.
Cheers!

Related

Determining the big-O of three nested for loops with if statment

What is the big-O for the following code :
y=1;
x=3;
for(int i =1 ; i < =n ; i*=2)
for(int j =1; j<= i * i; j++)
if (i % j == 0)
for(int k = 1; k<=j; k++)
y=y*x;
My Thoughts :
Looking at another similar questions I think the inner most loop is O(n) and the first loop is O(log (n))..as for the middle its O(n^2)
so the overall result would be O(log(n)*n^3)
Is my answer and way of thinking right ? I'm new to this so i hope i can get some help explaning how this loops work.
the most inner loop will run j time if i % j == 0. As the middle loop will run i^2 times, only when j < i it will be possible to satisfy the specified condition. Hence, among i^2 iteration of the middle loop, at least i^2 - i times, the condition will not be satisfied.
Suppose we denote the number of divisors of i with tau(i), among j < i only tau(i) times the condition will satisfy that means the total complexity of the most inner loop is equal to the sum of divisions of i which is at most 77/16 i (see this post for the proof).
Hence, the total complexity of the middle loop with the inner loop is at most (i^2 - i) + (i - tau(i)) + 77/16 i = i^2 + 77/16 i - tau(i).
We also know that the tau(i) is in O(i^(1/loglog(i))) (see the proof here). Now, to find the complexity of the whole loop, we need to sum the last expression for i = 1, 2, 4, ..., n. As we desire to find the asymptotic complexity and we have a sum here, we can ignore the lower powers of i. Therefore, the time complexity of the whole loop is 1 + 2^2 + (2^2)^2 + ... + (2^2)^log(n) = ((2^2)^(log(n)+1)-1)/(2^2-1) = Theta(n^2) (a geometric sum with factor of 2^2 and log(n) items).
In sum, the higher time complexity analysis for the specified code is Theta(n^2) which is also in O(n^2) as well.

How do I calculate this logarithmic complexity using summations?

My Question
What is the Big-O complexity for this code snippet?
Consider n as a power of 4.
for(int i = 1; i <= n; i = i*4)
for(int k = 1; k <= i; k++)
// constant statement
What I know so far
I tried making this code into a summation to find the complexity.
This is what I got:
I got (base 4) log(n) by computing the series 4, 4^2, 4^3 ... 4^r = n.
r = (base 4) log(n).
I'm now stuck at this summation:
Please let me know If I'm doing something wrong or there is another way to do this.
You’re on the right track here, but your innermost summation is wrong. You are right that the outer loop will iterate log_4 n times, but you’ve set up the outer sum so that i counts up as 1, 2, 3, ..., log_4 n, rather than 4^0, 4^1, 4^2, ... 4^log_4 n. As a result, that inner summation’s upper bound is incorrect. The bound should be 4^i, not i.
If you set things up this way, you’ll find that the overall sum is
4^0 + 4^1 + 4^2 + ... + 4^log_4 n
= (4^(log_4 n + 1) - 1) / (4 - 1) (using the formula for the sum of a geometric series
= (4(4^log_4 n) - 1) / 3
= (4n - 1) / 3
= Θ(n).
You may use wolframalpha to get the result for extreme accuracy.
https://www.wolframalpha.com/input/?i=sum+i,+i%3D1+to+log_4(n)

Algorithm complexity for this function

def mystery(L):
sum1 = 0
sum2 = 0
bound = 1
while bound <= len(L):
i = 0
while i < bound:
j = 0
while j < len(L):
if L[j] > L[i]:
sum1 = sum1 + L[j]
j = j + 2
j = 1
while j < len(L):
sum2 = sum2 + L[j]
j = j*2
i = i + 1
bound = bound * 2
return sum1 + sum2
I am having trouble finding the complexity of this function. I got to the i loop and don't know what to do.
It's a bit tricky to sort out how many times the middle level while loop runs. The outer loop increases bound by a factor of two on each pass (up to len(L)), which means the i loop will run O(bound) times per pass for O(log(N)) passes (where N is len(L)). The tricky part is how to add up the bound values, since they're changing on each pass.
I think the easiest way to figure out the sum is to start with the largest bound, just before the loop quits. First, lets assume that N (aka len(L)) is a power of 2. Then the last bound value will be exactly equal to N. The next smaller one (used on the next to last iteration) will be N/2 and the next after that will be N/4. Their sum will be:
N + N/2 + N/4 + N/8 + ... + 1
If we factor out N from each term, we'll get:
N*(1 + 1/2 + 1/4 + 1/8 + ... + 1/N)
You should recognize the sum in the parentheses, it's a simple geometric series (the sum of the powers of 1/2), which comes up pretty often in mathematics and analysis. If the sum went on forever, it would add up exactly to 2. Since we're quitting a bit early, it will be less than two by an amount equal to the last term (1/N). When we multiply the N term in again, we get the whole thing as being run 2*N - 1 times, so the loop is O(N)
The same Big-O bound works when N is not exactly a power of 2, since the values we added up in the analysis above will each serve as the upper bound for one of the actual bound values we will see in the loop.
So, the i loop runs O(N) times.

Is this algorithm in N^2?

int sum = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= i*i; j++)
sum++;
Is this complexity 1 + 2^2 + 3^2 + 4^2 ... + N^2? How to represent it in big-o notation?
The sum is N(N+1)(2N+1)/6 so your algorithm is O(N^3).
If you expand the sum you have 1/3 * N^3 + ...
You can see it simply by plotting the values of sum after running the algorithm for different values of N:
Straightforwardly, using Sigma notation:
Another way to look at it is to use the "worst case" analysis.
Originally, we have:
The outer for loop will run N times
The inner for loop will run i*i times
This might be confusing since i seems to be changing based on the outer for loop.
However, in the "worst case" scenario, the largest value that i ever attains is N.
Therefore, just substitute N instead of i in our analysis.
Now we have:
The outer for loop will run N times
The inner for loop will run N*N times
And the time complexity of this situation is of course O(N³).
you can always use the intuitive way.
for i = 2 second loop 1 time, first loop 1 time. 1*1
for i = 3 second loop 9 times, first loop 2 times. 9*2
for i = 4 second loop 16 times, first loop 3 times 16*3
for i = 5 second loop 25 times, first loop 4 times. 25*4
.
.
.
you can see the pattern easily. it is (nˆ2)*(n-1) therefore its big o should be O(nˆ3)

Runtime of for loop

What's the runtime for this nested for loop in big O notation?
for(i = 1 to k)
{
for(j = i+1 to k)
{}
}
It's smaller than O(k^2) but I can't figure it out.
Your question is closely related to the series sum S(k) = 0 + 1 + 2 + ... + (k-2) + (k-1). It can be shown that S(k) = (k*(k-1))/2 = (k*k)/2 - k/2. [How? Reorder the sum as S(k) = {0+(k-1)} + {1+(k-2)} + {2+(k-3)} + .... This shows how.]
Therefore, is the algorithmic order smaller than O(k*k)? Remember that constant coefficients like 1/2 do not influence the big O notation.
Question: So it's equivalent to replacing j = i+1 to k with j = 1 to k?
Answer: Right. This is tricky, so let's think it through. For i == 1, how many times does the inner loop's action run? Answer: it runs k-1 times. Again, for i == 2, how many times does the inner loop's action run? Answer: it runs k-2 times. Ultimately, for i == k, how many times does the inner loop's action run? Answer: it runs zero times. Therefore, over all values of i, how many times does the inner loop's action run? Answer: (k-1) + (k-2) + ... + 0, which is just the aforementioned sum S(k).

Resources