Consider the complexity as a function of the number n
of characters in C
. Let's call that f(n)
.
The first if
blocks are just doing simple checks no matter what, so we can ignore them for now (constant complexity).
The meat of the algorithm is of course these lines:
((*C == *A) && isInterleaved(A+1, B, C+1))
|| ((*C == *B) && isInterleaved(A, B+1, C+1));
Checks (*C == ...)
are again constant time complexity. Now, isInterleaved(..., ..., C+1)
is calling the algorithm with a C
shorter by 1: it's complexity is therefore f(n-1)
.
We can then put it all together as:
f(n) =
k1 +
(k2 + f(n-1)) +
(k3 + f(n-1))
With k1
, k2
and k3
being some constants. Reorder the terms, we get:
f(n) = 2 * f(n-1) + k
Where k
is, again, some constant. Now, expanding the recursion, we get:
f(n) = 2 * (2 * ( 2 * (... f(0) + k0) + k1) + k2) + ... + k_n)
= 2 * (2 * (2 * (... 2*(2*(f(0) + k0) + k1) + k2) + ... + k_n)
= 2 * (2 * (2 * (... 2*(2^2*(f(0) + k0) + 2*k1) + k2) + ... + k_n)
= 2 * (2 * (2 * (... 2*(2^3*(f(0) + k0) + 2^2*k1 + 2*k2) + ... + k_n)
f(n) = 2^n * (f(0) + k0) + 2^(n-1) * k1 + 2^(n-2) * k2 + ...
Dividing that all by 2^n
, we get:
f(n) / 2^n = (f(0) + k0) + k1 / 2 + k2 / 4 + ... + k_n / 2^n
All of these terms are bounded: It is a property of the sum of 2^{-n}
that it will approach 2 without ever reaching it, no matter how many terms you sum. Now, since all your k
constants are just simple checks, it makes sense that they are also all bounded. Therefore, we know that there exist some constant K
such that k0 < K, k1 < K, ..., k_n < K
. Your f(n)/2^n
then becomes:
f(n) / 2^n < f(0) + K * (1 + 1/2 + 1/4 + ... + 1/2^n)
Now, the first two checks ensure that f(0)
is constant as well, so you have proven that the complexity of that function divided by 2^n is indeed bounded, which is sufficient to say that f(n) is O(2^n)
.
You can skim over most of these 'there exists a constant such that...'; the main observation to make is (using the 'handwavily equivalent-ish' symbol ~
):
f(n) ~ f(n-1) + f(n-1)
f(n) ~ 2 * f(n-1)
f(n) ~ O(2^n)
I have also slightly cheated by starting from the assumption that the length of C
is the only parameter that matters for computing the complexity, but how you can rigorously show that the complexity is equivalent for various lengths of A
and B
is left as an exercise to the reader !