0

I'm preparing for an exam and these are some of problems from last year's tests. The task is to calculate both exact and asymptotic complexity. How would you solve it? Universally, if possible.

for ( i = j = 0; i < n; j ++ ) {
  doSomething ();
  i += j / n;
  j %= n;
}

for ( i = 0; i < 2 * n; i += 2 )
  for ( j = 1; j <= n; j <<= 1 )
    if ( j & i )
      doSomething ();

for (i = 0; i < 2*n; i++) {
  if ( i > n )
    for (j = i; j < 2 * i; j ++ ) doSomething();
  else
    for (j = n; j < 2 * n; j ++ ) doSomething();
}

Thanks in advance

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • I don't understand the sense of the first one. Well, it's like `for (0 to 199) { for (0 to 200) { /* .. */ } }`, but.. well nahh – Niklas R Jan 08 '13 at 12:51
  • The sense is in testing our knowledge of C and algorithmization. Would you explain how did you come to your result? –  Jan 08 '13 at 12:56
  • Forgot to add that I defined `n` to be `200`. – Niklas R Jan 08 '13 at 13:06

3 Answers3

2

My solution for the third loop is

t(n) = [ (n-1)*n +  ((n-1)*n)/2 ] *D  + [ n^2 +n ] *D + [ 2n ]*I

so it is in O(n^2) given that doSomething() has a constant time and that i and j are integers.

The second term ( [ n^2 +n ] *D ) is fairly easy.

The loop

for (j = n; j < 2 * n; j ++ ) doSomething();

gets called while i <= n so it will be called n+1 times, since it starts from 0.

The loop for (j = n; j < 2 * n; j ++ ) calls doSomething() n times, so we have (n+1)*n*D = [n^2+n] *D. I assume that doSomething() has a constant time which is equal to D

The first term is a little bit more complex.

for (j = i; j < 2 * i; j ++ ) doSomething();

gets called when i>n so it will be called n-1 times. The loop calls doSomething() i times. The first time it gets called n+1, the second time ´n+2´ and so on until it is 2n-1 which is equal to n + (n-1). So we get a sequence likes this {n+1, n+2, n+3, ... , n+(n-1)}.

If we sum up the sequence we get n-1 times n and the sum 1+2+3+...+ (n-1). The last term can be solved with the "Gaußsche Summenformel" (sorry I don't have the English name for it but you can see the formula in the German wiki link) so it is equal to ((n-1)*n)/2

So the first term is (n-1) * n + ((n-1)*n)/2 *D

And the last term is therefor the if statement which is called 2*n*I, where I is the time to execute the If statement.

Raphael Ahrens
  • 953
  • 15
  • 29
1

Well, the question here is, for all three loop structures, how the amount of iterations changes in proportion to n, right? so let's look at the loops. I'll omit the first one, since you solved it already.

for ( i = 0; i < 2 * n; i += 2 )
  for ( j = 1; j <= n; j <<= 1 )
    if ( j & i )
      doSomething ();

the outer for loop obviously runs exactly n times. the inner loop runs log_2(n) times, because of the bitwise shift operation. The if clause runs in constant time, so the entire loop is in O(n * log_2(n)), assuming that doSomething() is in constant time as well.

Does that make it clearer? :)

Andreas Grapentin
  • 5,499
  • 4
  • 39
  • 57
1

As per request, I will explain how I came to the result that the first loop is equal to a construction like this:

int i, j;
for (i=0; i < n; i++) {
    for (j=0; j <= n; j++) {
        doSomething();
    }
}

First of all, I must admit that before I really thought about it, I just wrote a little sample program including the first of the three for-loops that prints out i and j during the iteration. After I've seen the results, I was thinking about why the results are like this.

In the comment, I forgot to add that I defined n=200.

Explanation

We can say, that although j is incremented regularly every step in the iteration, it will never exceed a value of n. Why? After n iterations, j==n. It will be set to 0 in the statement j %= n after i has been incremented. In the statement i += j / n, i will be incremented by 0 n-1 times, and at the nth time, it will be incremented by 1. This starts all over again until i >= n.

Niklas R
  • 16,299
  • 28
  • 108
  • 203