简体   繁体   中英

How to calculate running time of algorithm?

I am currently learning about Big O Notation running times. I try to calculate the time complexity of some code:

int i = 1;
int n = 3;  //this variable is unknown
int j;

while (i<=n)
{
    for (j = 1; j < i; j++)
        printf_s("*");
    j *= 2;
    i *= 3;
}

I think that complexity of this code is О(log n). But even if it is correct, I can`t explain why.

The body of the inner loop is going to be executed 1, 3, 9, 27, ..., 3^k times, where k = ceil(log 3 (n)).

Here we can use the fact that Σ 0 <= i < k 3 i <= 3 k . One can prove it by induction.

So we can say that the inner loop executes no more than 2*3^k times, where 3^k < 3n, which is linear in n, namely O(n) .

The time complexity is not O(log n) , it is O(n) .

We can calculate that in a structured way. First we examine the inner loop:

for (j = 1; j < i; j++)
    printf_s("*");

Here j iterates from 1 to i . So that means that for a given i , it will take i-1 steps.

Now we can look at the outer loop, and we can abstract away the inner loop:

while (i<=n)
{
    // ... i-1 steps ...
    j *= 2;
    i *= 3;
}

So each iteration of the while loop, we perform i-1 steps. Furthermore each iteration the i doubles, until it is larger than n . We thus can say that the number of steps of this algorithm is:

log3 n
---
\       k
/      3  - 1
---
k=0

We here use k as an extra variable that starts at 0 and each time increments. It thus counts how many times we perform the body of the while loop. It will end when 3^k > n , hence we will iterate log 3 ( n ) times, and each iteration the inner loop will resut in 3 k -1 steps.

The above sum is equivalent to:

          log3 n
           ---
           \       k
-log3 n +  /      3
           ---
           k=0

The above is a geometric series [wiki] , which is equal to: (1-3 log 3 n )/(1-3) , or simplified, it is equal to (n log 3 3 -1)/2 , and hence (n-1)/2 .

The total number of steps is thus bounded by: (n-1)/2 - log 3 n , or formulated more simply O(n) .

First of all, you're really calculating the running time, but the number of time-consuming operations. Here, each call to printf_s is one.


Sometimes if you're not good at maths, you can still find the number with experimentation. The algorithm compiled with -O3 is quite fast to be tested with various n . I replaced printf_s with a simple increment to a counter that is then returned from the function, and use unsigned long long as the type. With those changes we get

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <inttypes.h>

unsigned long long alg(unsigned long long n) {
   unsigned long long rv = 0;
   unsigned long long i = 1;
   unsigned long long j;

   while (i <= n) {
       for (j = 1; j < i; j++)
           rv += 1;

       i *= 3;
   }
   return rv;
}

int main(void) {
    unsigned long long n = 1;
    for (n = 1; n <= ULONG_MAX / 10; n *= 10) {
        unsigned long long res = alg(n);
        printf("%llu %llu %f\n", n, res, res/(double)n);
    }
}

the program runs in 0.01 seconds because GCC is clever enough to completely eliminate the inner loop. The output is

1 0 0.000000
10 10 1.000000
100 116 1.160000
1000 1086 1.086000
10000 9832 0.983200
100000 88562 0.885620
1000000 797148 0.797148
10000000 7174438 0.717444
100000000 64570064 0.645701
1000000000 581130714 0.581131
10000000000 5230176580 0.523018
100000000000 141214768216 1.412148
1000000000000 1270932914138 1.270933
10000000000000 11438396227452 1.143840
100000000000000 102945566047294 1.029456
1000000000000000 926510094425888 0.926510
10000000000000000 8338590849833250 0.833859
100000000000000000 75047317648499524 0.750473
1000000000000000000 675425858836496006 0.675426

And from that we can see that the ratio of number of prints to n is not really converging, but it seems to be very much bounded by constants on both sides, thus O(n).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM