Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating the complexity of an algorithm with 3 loops

I tried to solve the following exercise :

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; i++)
    for (int j = 1; j <= i*i; j++)
        for (int k = 1; k <= j*j; k++)
            sum++;

and I found that the complexity is O(n4), however the correct answer is :

The answer is : N7

For a given value of i, the body of the innermost loop is executed 12 + 22 + 32 + ... + (i2)2 ~ 1/3 i6 times. Summing up over all values of i yields ~ 1/21 N7.

I would like some help to understand this answer and the correct way to calculate complexity in this case.

EDIT : In particular, I don't understand this statement :

12 + 22 + 32 + ... + (i2)2 ~ 1/3 i6

Because for me, 2 + 22 + 32 + ... + (i2)2 ~ i4

like image 539
otus Avatar asked Dec 02 '22 17:12

otus


2 Answers

EDIT:

I'll add a bit of explanation to clear up your confusion about the quote in your question. Let's consider a fixed value of i and focus on the innermost two loops:

for (int j = 1; j <= i*i; j++)
    for (int k = 1; k <= j*j; k++)
        sum++;

How many times is the j-loop iterated? The answer is i^2 times. On each of those iterations, the k-loop is iterated j^2 times, which is different for each outer iteration because the value of j increases from 1 all the way to i^2.

When j = 1, the k-loop iterates 1^2 times. When j = 2, the k-loop iterates 2^2 times. When j=3, 3^2 times. Tallying up the total number of the iterations of the k-loop over all values of j, you have 1^2 + 2^2 + 3^2 + ... + (i^2)^2, since j runs between 1 and i^2. Hopefully that clarifies how you arrive at the following statement:

For a given value of i, the body of the innermost loop is executed 12 + 22 + 32 + ... + (i2)2 ~ 1/3 i6 times.


The total number of iterations can be expressed in sum form. The innermost loop has exactly j^2 iterations for each (varying) value of j, the middle loop has i^2 iterations for each value of i, and the outermost loop has N iterations. More neatly, the exact number of iterations is:

enter image description here

Multiplying through, you'll find this is a 7th order polynomial in N, so it is apparent why this is O(N^7).

In case you doubt the answer above is correct, simply run your own code and compare the value of sum you get with the formula provided above:

var sum = 0;
var N = 10;

for (var i = 1; i <= N; i++)
    for (var j = 1; j <= i*i; j++)
        for (var k = 1; k <= j*j; k++)
            sum++;

function T(N) { return (1/420)*N*(1+N)*(1+2*N)*(8+11*N+21*N*N+20*N*N*N+10*N*N*N*N); }

console.log(sum===T(N));

Here's a demo: http://jsfiddle.net/wby9deax/. No matter what value of N you put in the answer will be correct (note: be careful with large values for N, it will probably freeze up your browser, since the number of iterations grows very rapidly).

like image 198
Asad Saeeduddin Avatar answered Dec 25 '22 18:12

Asad Saeeduddin


int sum = 0;
for (int i = 1; i <= N; i++)            -- O(N^1)
    for (int j = 1; j <= i*i; j++)      -- O(N^2)
        for (int k = 1; k <= j*j; k++)  -- O(N^4)
            sum++;

Since they're nested (and since they're all linear) you get O(N1 × N2 × N4) = O(N1+2+4) = O(N7)


EDIT : In particular, I don't understand this statement :

12 + 22 + 32 + ... + (i2)2 ~ 1/3 i6

Keep in mind that you may have N terms hiding in the "…" part.

like image 35
aioobe Avatar answered Dec 25 '22 18:12

aioobe