Search code examples
algorithmtime-complexitycomplexity-theoryasymptotic-complexity

How to effectively calculate an algorithm's time complexity?


I'm studying algorithm's complexity and I'm still not able to determine the complexity of some algorithms ... Ok I'm able to figure out basic O(N) and O(N^2) loops but I'm having some difficult in routines like this one:

// What is time complexity of fun()? int fun(int n) { int count = 0; for (int i = n; i > 0; i /= 2) for (int j = 0; j < i; j++) count += 1; return count; }

Ok I know that some guys can calculate this with the eyes closed but I would love to to see a "step" by "step" how to if possible.

My first attempt to solve this would be to "simulate" an input and put the values in some sort of table, like below:

for n = 100 Step i 1 100 2 50 3 25 4 12 5 6 6 3 7 1

Ok at this point I'm assuming that this loop is O(logn), but unfortunately as I said no one solve this problem "step" by "step" so in the end I have no clue at all of what was done ....

In case of the inner loop I can build some sort of table like below:

for n = 100 Step i j 1 100 0..99 2 50 0..49 3 25 0..24 4 12 0..11 5 6 0..5 6 3 0..2 7 1 0..0

I can see that both loops are decreasing and I suppose a formula can be derived based on data above ...

Could someone clarify this problem? (The Answer is O(n))


Solution

  • Another simple way to probably look at it is:

    Your outer loop initializes i (can be considered step/iterator) at n and divides i by 2 after every iteration. Hence, it executes the i/2 statement log2(n) times. So, a way to think about it is, your outer loop run log2(n) times. Whenever you divide a number by a base continuously till it reaches 0, you effectively do this division log number of times. Hence, outer loop is O(log-base-2 n)

    Your inner loop iterates j (now the iterator or the step) from 0 to i every iteration of outer loop. i takes the maximum value of n, hence the longest run that your inner loop will have will be from 0 to n. Thus, it is O(n).

    Now, your program runs like this:

    Run 1: i = n, j = 0->n
    Run 2: i = n/2, j = 0->n/2
    Run 3: i = n/4, j = 0->n/4
    .
    .
    .
    Run x: i = n/(2^(x-1)), j = 0->[n/(2^(x-1))]
    

    Now, runnning time always "multiplies" for nested loops, so O(log-base-2 n)*O(n) gives O(n) for your entire code