Order Of Growth complicated for loops - algorithm

For the following code fragment, what is the order of growth in terms of N?
int sum = 0;
for (int i = 1; i <= N; i = i*2)
for (int j = 1; j <= N; j = j*2)
for (int k = 1; k <= i; k++)
sum++;
I have figured that there is lgN term, but I am stuck on evaluating this part : lgN(1 + 4 + 8 + 16 + ....). What will the last term of the sequence be? I need the last term to calculate the sum.

You have a geometric progression in your outer loops, so there is a closed form for the sum of which you want to take the log:
1 + 2 + 4 + ... + 2^N = 2^(N+1) - 1
To be precise, your sum is
1 + ... + 2^(floor(ld(N))
with ld denoting the logarithm to base 2.
The outer two loops are independent from each other, while the innermost loop only depends on i. There is a single operation (increment) in the innermost loop, which means that the number of visits to the innermost loop equals the summation result.
\sum_i=1..( floor(ld(N)) ) {
\sum_j=1..( floor(ld(N)) ) {
\sum_k=1..2^i { 1 }
}
}
// adjust innermost summation bounds
= \sum_i=1..( floor(ld(N)) ) {
\sum_j=1..( floor(ld(N)) ) {
-1 + \sum_k=0..2^i { 1 }
}
}
// swap outer summations and resolve innermost summation
= \sum_j=1..( floor(ld(N)) ) {
\sum_i=1..( floor(ld(N)) ) {
2^i
}
}
// resolve inner summation
= \sum_j=1..( floor(ld(N)) ) {
2^(floor(ld(N)) + 1) - 2
}
// resolve outer summation
= ld(N) * N - 2 * floor(ld(N))
This amounts to O(N log N) ( the second term in the expression vanishes asymptotically wrt to the first ) in Big-Oh notation.

To my understanding, the outer loop will take log N steps, the next loop will also take log N steps, and the innermost loop will take at most N steps (although this is a very rough bound). In total, the loop has a runtime complexity of at most ((log N)^2)*N, which can probably be improved.

Related

How to calculate Time Complexity in the Big O notation for following array double lookup

What will be time complexity of the following algorithm ?? Can some one help
public class Util
{
public static int GetDistance(int[] array)
{
//Find the max seperation of two same numbers inside an array for example
// {1,2,4,1,5,9,0,4,15,1,2} should return 9 ( position of '1' at 9th and 0th location)
int N = array.Length;
int maxDistance=0;
for (int i = 0; i < N; i++)
{
for (int j = (N-1); j > i; j--)
{
if (array[j]==array[i])
if(maxDistance < (j-i))
maxDistance = j- i;
}//End of inner for
}//End of for
System.Console.WriteLine("maxDistance " + maxDistance);
return maxDistance ;
} //End of Function
} //End of Class
You look at the inner loop (the operation inside the inner loop take constant time). The inner loop is executed exactly N-1-i times.
Then the outer loop is executed exactly N times, with increasing values of i. The total workload involves
(N-1) + (N-2) + (N-3) + ... + 1
executions of the inner body. This sum is a triangular number and it is not a big deal to show that it equals
(N-1).N / 2
This is O(N²).
You have two for loop which iterate N times (the second is also impact by the number N, meaning N bigger, the iteration number bigger).
Inside the loop, the operation is O(1)
So totally you have O(1) * O(N^2) = O(N^2)

Can't understand big-O of a nested loop

I am having problem understanding the answer to the following question about analyzing two algorithms below.
for (int i = n ; i >= 1; i = i/2) {
for ( int j = 1; j <= n ; j++) {
//do something
}
}
The algorithm above has complexity of O(n) according to the answers. Shouldn't it be lower since the outer loop always halves the amount we have to go through. I thought that it should be something along the lines of O(n/2 * )?
for ( int j = 1; j <= n ; j++ ) {
for ( int i = n ; i >= j ; i = i / 2 ) {
//do something
}
}
This one is O(n log n) if I am correct?
The first iteration will execute n steps, the second will execute n/2, the third will execute n/4, and so on.
If you compute the sum of n/(2^i) for i=0..log n you will get roughly 2n and that is why it is O(n).
If you take n out of the summation and sum only the 1/(2^i) part, you will get 2. Take a look at an example:
1 + 1/2 + 1/4 + 1/8 + 1/16 + ... = 1 + 0.5 + 0.25 + 0.125 + 0.0625 + ... = 2
Each next element is twice smaller, therefore the sum will never exceed 2.
You are right with the second nested loop example - it is O(n log n).
EDIT:
After the comment from ringø I re-read the question and in fact the algorithm is different from what I understood. ringø is right, the algorithm as described in the question is O(n log n). However, judging from the context I think that the OP meant an algorithm where the inner loop is tied to i and not n.
This answer relates to the following algorithm:
for (int i = n ; i >= 1; i = i/2) {
for ( int j = 1; j <= i ; j++) {
//do something
}
}

What is the big O notation and how do I calculate it?

Calculate big o of function. How do I calculate the big O notation in this function?
Example:
function fun1(int n)
{
int s = 0;
for(int i = 0; s < n; i++)
{
s += i;
for(var j = s; j < n; j++)
{
console.log(j);
}
}
return s;
}
Roughly speaking, consider the i-th iteration of the outer loop. After execution of the loop's body,
s = 1 + 2 + ... + i-1 + i
which is equal to i*(i+1)/2 = (i²+i)/2 by an identity by Gauss. The maximum value for i such that this expression is smaller than n is can be obtained by elementary calculation as follows. If we require
(i²+i)/2 <= n
which means
i²+i-2n <= 0
we can use the formula for reduced quadratic equation to obtain
i <= -1/2 + sqrt(1/4+2n)
which is in O(n^{1/2}). In each iteration of the outer loop, the inner loop takes n-s iterations, which very roughly can be estimated by n (but this is very imprecise, I believe the overall analysis can be made more precise). In total, this yields a bound of O(n^{1/2}*n)=O(n^{3/2}).

Calculating the big-O complexity of this selection sort implementation?

I'm trying to compute the big-O time complexity of this selection sort implementation:
void selectionsort(int a[], int n)
{
int i, j, minimum, index;
for(i=0; i<(n-1); i++)
{
minimum=a[n-1];
index=(n-1);
for(j=i; j<(n-1); j++)
{
if(a[j]<minimum)
{
minimum=a[j];
index=j;
}
}
if (i != index)
{
a[index]=a[i];
a[i]=minimum;
}
}
}
How might I go about doing this?
Formally, you can obtain the exact number of iterations with the order of growth using the methodology below:
Executing the following fragment code (synthetic version of the original code), sum will equal the closed form of T(n).
sum = 0;
for( i = 0 ; i < ( n - 1 ) ; i ++ ) {
for( j = i ; j < ( n - 1 ) ; j ++ ) {
sum ++;
}
}
Let's begin by looking at the inside of the outer loop. It does O(1) work with the initial assignments, then has a loop that runs n - i times, then does O(1) more work at the end to perform the swap. Therefore, the runtime is Θ(n - i).
If we sum up from i going from 0 up to n - 1, we get the following:
n + (n - 1) + (n - 2) + ... + 1
This famous sum works out to Θ(n2), so the runtime would be Θ(n2), matching the known runtime of this algorithm.
Hope this helps!

Big O for while loops

I had this question for my assignment the other day, but I was still unsure if I'm right.
for(int i =1; i <n; i++) //n is some size
{
for(j=1; j<i; j++)
{
int k=1;
while (k<n)
{
k=k+C; //where C is a constant and >=2
}
}
}
I know the nested for loops is O(n^2) but I wasn't sure with the while loop. I assumed that the whole code will be O(n^3).
The inner loop is literally O(n/C)=O(n), so yes, overall it's O(n^3) (the second loop has an upper bound of O(n))
int k=1;
while (k<n){
k=k+C //where C is a constant and >=2
}
This will take (n-1)/C steps: write u = (k-1)/C. Then, k = Cu + 1 and the statement becomes
u=0;
while(u < (n-1)/C) {
u=u+1
}
Hence the while loop is O(n) (since C is constant)
EDIT: let me try to explain it the other way around.
Start with a dummy variable u. The loop
u=0;
while(u < MAX) {
u = u+1
}
runs MAX times.
When you let MAX = (n-1) / C, the loop is
u=0;
while(u < (n-1)/C) {
u=u+1
}
And that runs (n-1)/C times.
Now, the check u < (n-1)/C is equivalent to C*u < n-1 or C*u + 1 < n, so the loop is equivalent to
u=0;
while(C*u + 1 < n) {
u=u+1
}
Now, suppose that we rewrote this loop in terms of a variable k = C * u + 1. Then,
u=0;
k=1; // C * 0 + 1 = 1
The loop looks like
while(C*u + 1 < n) {
while(k < n) {
and the inner condition is
u=u+1
k=k+C //C * (u+1) + 1 = C * u + 1 + C = old_k + C
Putting it all together:
int k=1;
while (k<n){
k=k+C
}
takes (n-1)/C steps.
Formally, you may proceed using the following methodology (Sigma Notation):
Where a symbolizes the number of constant operations inside the innermost loop (a = 1 if you want to count the exact number of iterations).
Well, you would need to look at how many times the while loop body is run for a given value of n and C. For example n is 10 and C is 3. The body would run 3 times: k = 1, k = 4, k = 7. For n = 100 and C = 2, the body would run 50 times: k = 1,3,5,7,9,...,91,93,95,97,99. It is a matter of counting by C until n. You should be able to calculate the Big-O complexity from that clue.

Resources