Steven
Steven

Reputation: 11

Calculating Big O complexity of these algorithms?

I am trying to figure out the Big O notation of the following 2 algorithms below but am having trouble.

The first one is:

public static int fragment3 (int n){
int sum = 0;
for (int i = 1; i <= n*n; i *= 4)
  for (int j = 0; j < i*i; j++)
   sum++;
  return sum;
} //end fragment 3

The answer should be O(n^4). When I try to do it myself this is what I get: I look at the first for loop and think it runs n^2 logn times. Then for the inner for loop, it runs n times + the run time of the outer loop which is n^3 logn times. I know this is wrong but just don't get it.

For the code fragment below, the answer is O(n^9).

public static int fragment6(int n) {
int sum = 0;
for(int i=0; i < n*n*n; i++) {
  if(i%100 == 0) {
    for(int j=0; j < i*i; j += 10)
      sum++;
  } // if
  else {
    for(int k=0; k <= i; k++)
      sum++;
  } // else
 } // outer loop

 return sum;
} // fragment 6

When I attempt it I get: n^3 for the outer for loop. for the if statement I get n, for the second for loop I get n + the other for loop and if statement, making it n^5. Finally, I get n for the final for loop and everything adds up to O(n^6).

What am I doing wrong and what is the correct way to get its O(n^9) complexity?

Upvotes: 1

Views: 238

Answers (3)

Christopher Oezbek
Christopher Oezbek

Reputation: 26303

First case:

  • Last run of the inner-loop with i = n^2, runs for n^4. The outer-loop up to n^2, but using exponential growth. For summation the sum over all inner-loop runs but the last is less than the last run. So inner-loop is essentially contributing O(1).

Second case:

  • 100 % n == 0 does not matter really in O thinking
  • else part does not matter, it is much less than main part
  • outer-loop runs from 0 to n^3 => n^3
  • inner-loop runs from 0 to n^6 => n^6
  • outer-loop times inner-loop => n^9

Upvotes: 0

avysk
avysk

Reputation: 2035

For the first one.

Let's look at the inner loop..

At the first iteration of the outer loop (i=1) it runs 1 time. At the second iteration (i=4) it runs 16 (4*4) times. At the third iteration (i=16) it runs 256 (16*16) times. In general, at the (k+1)-th iteration of the outer loop inner loop runs f1 times, as f2 at that iteration. So the total number of iterations will be

f3

Now, how many numbers in that sum we will have? To determine that we should have a look at the outer loop. In it i grows as f2, until it reaches f4. So the total number of iterations is f5.

This means that the total number of runs of inner loop is

f6 (by dropping all the numbers from the sum but the last one).

Now we know, that the inner loop runs at least f7 times, so we are not faster than O(n^4).

Now,

f8

Solving for N,

f9 where C is a constant, so we're not slower than O(n^4).

Upvotes: 3

Paul Hankin
Paul Hankin

Reputation: 58201

Your approach to computing big-O is flat-out wrong, and you've made computation errors.

In some common cases you can take the worst case number of iterations and multiply them together, but this isn't a sound method and fails for cases like this:

for (i = 1; i < n; i *= 2) {
   for (j = 0; j < i; j++) {
      sum++;
   }
}

Here, the outer loop runs log_2(n) times, and the inner loop worst case is n iterations. So the wrong method that you're using will tell you that the complexity of this code is O(n log n).

The correct method is to count accurately the number of iterations, and approximate at the end only. The number of iterations is actually:

1 + 2 + 4 + 8 + ... + 2^k

where 2^k is the largest power of two less than n. This sum is 2^(k+1) - 1, which is less than 2n. So the accurate complexity is O(n).

Applying this idea to your first example:

for (int i = 1; i <= n*n; i *= 4)
    for (int j = 0; j < i*i; j++)
        sum++

i takes the values 4^0, 4^1, 4^2, ..., 4^k where 4^k is the largest power of 4 less than or equal to n^2.

The inner loop executes i^2 times for a given value of i.

So overall, the inner sum++ is executed this many times:

(4^0)^2 + (4^1)^2 + ... + (4^k)^2
= 2^0 + 4^2 + ... + 4^2k
= 16^0 + 16^1 + ... + 16^k
= (16^k - 1) / 15

Now by definition of k we have n^2/4 < 4^k <= n^2. So n^4/16 < 4^2k <= n^4, and since 16^k = 4^2k, we get that the total number of times the inner loop is executed is O(16^k) = O(n^4).

The second example can be solved using a similar approach.

Upvotes: 2

Related Questions