Reputation: 11
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
Reputation: 26303
First case:
Second case:
Upvotes: 0
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 times, as at that iteration. So the total number of iterations will be
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 , until it reaches . So the total number of iterations is .
This means that the total number of runs of inner loop is
(by dropping all the numbers from the sum but the last one).
Now we know, that the inner loop runs at least times, so we are not faster than O(n^4).
Now,
Solving for N,
where C is a constant, so we're not slower than O(n^4).
Upvotes: 3
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