Let's look at the first loop first:
int i = m;
while (i > 100)
i = i/3;
Can be described as T(i) = O(1) + T(i/3)
, since you're doing some const work (condition comparison etc.) and then reiterating the loop with a value smaller by a third. If we'll expand it by recursion, we'll get:
T(i) = O(1) + T(i/3)
= O(1) + O(1) + T(i/3/3) = 2*O(1) + T(i/9)
= 2*O(1) + O(1) + T(i/9/3) = 3*O(1) + T(i/27)
= ... = n*O(1) + T(i/3^n)
The last statement being for the n-th iteration. Now, the loop would stop i/3^n <= 100
which means when n = log3(i/100)
. So you'll do log(i)
operations, which means the first loop's complexity is O(log(i))
. (note that you've set i=m so this is basically O(log(m))
).
Now let's look at the second loop:
for (int k=i ; k>=0; k--) {
for (int j=1; j<n; j*=2)
System.out.print(k + "\t" + j);
System.out.println();
}
The inner loop can be described as T(n) = O(1) + T(2*n)
. Let's expand:
T(j) = O(1) + T(2j) = O(1) + O(1) + T(2*2j) = 2*O(1) + T(4j)
= 2*O(1) + O(1) + T(2*4j) = 3*O(1) + T(8j)
= ... = l*O(1) + T((2^l)*j)
Again, the last one being for the l-th iteration. So you'll stop once (2^l)*j = n
, which means when j=log(n)
. So the inner loop complexity is O(log(n))
.
Now let's look at the outer loop. It could be described as T(k) = O(log(n)) + T(k-1)
. Let's expand:
T(k) = O(log(n)) + T(k-1) = O(log(n)) + O(log(n)) + T(k-1-1) = 2*O(log(n)) + T(k-2)
By this point, I'm sure you can see that by the l-th iteration you'll have l*O(log(n)) + T(k-l)
. You'll stop once k-l < 0
so when k=l
and so the complexity is O(k*log(n))
.
But what is k
? Well, k
is basically set to the value of i
which is m
chopped down log3
times. So you'll be doing log(n)
work for log(m)
times. So your complexity is O(log(m)*log(n))
.