Solving the Recurrence Relation T(n)=T(n-1)*T(n-2)+c where T(0)=1 and T(1)=2 - algorithm

I need to solve the recurrence relation for
T(n) = T(n - 1) * T(n - 2) + c where T(0) = 1 and T(1) = 2.
The algorithm computes 2f(n) where f(n) is the nth Fibonacci number. I assume that T(n - 2) is approximately equal to T(n - 1) and then I rewrite the relation as
T(n) = T(n - 1)^2 + c
and finality I reach to complexity of O(n). This the algorithm:
Power(n):
if n == 0 then x = 1;
else if n == 1 then x = 2;
else x = Power(n - 1) * Power(n - 2);
return x;
Is it true that the recurrence relation T(n) = T(n - 1) * T(n - 2) + c has O(n) complexity?

You are confusing multiplication in the algorithm with multiplication in the recurrence relation. You calculate Power(n - 1) and Power(n - 2) and multiply them, but this does not take T(n - 1) * T(n - 2) time. These values are computed separately, and then multiplied, taking T(n - 1) + T(n - 2) time, assuming constant-time multiplication.
The recurrence then becomes T(n) = T(n - 1) + T(n - 2) + c. We'll solve this by substitution. I'll skip choosing an n0; our induction hypothesis will be T(n) = d * 2^n - 1. (We need the -1 to allow of to later cancel the c; this is called strengthening the induction hypothesis, see e.g. here).
T(n) = T(n - 1) + T(n - 2) + c
= d * (2^(n - 1) - 1) + d * (2^(n - 2) - 1) + c (substitute by IH)
= 3d * 2^(n - 2) - 2d + c
<= d * 2^n - 2d + c (3 < 2^2)
<= d * 2^n (when d > c / 2)
Conclusion: T(n) ∈ O(2n).
Bonus fact: the tight bound is actually Θ(φn), where φ is the golden ratio. See this answer for an explanation.

First, the recurrence that models the running time is T(n) = T(n-1) + T(n-2) + C for T(1) = T(0) = 1, for some C>0. This is because you make two recursive calls, one on n-1 and the other on n-2.
The recurrence you have is precisely the Fibonacci recurrence if we forget the additional constant (which contributed a factor C in the end). The exact solution is this (image source: Wikipedia):
where
and
You could say that T(n) = Theta(1.618... ^ n).

Related

Recurrence relation T(n) = 3T(n-1) + n

I'm trying to solve the recurrence relation T(n) = 3T(n-1) + n and I think the answer is O(n^3) because each new node spawns three child nodes in the recurrence tree. Is this correct? And, in terms of the recurrence tree, is there a more mathematical way to approach it?
Recurrence equations are just math: Unfold, sum up and simplify.
T(n) = 3T(n-1) + n = 3 (3 T(n - 2) + (n-1)) + n
= 3^2 T(n - 3) + 3^2(n-2) + 3(n-1) + n)
= ...
= 3^i T(n - i) + Σ_(j=0..i-1) 3^j * (n-j)
= Σ_(j=0..n-1) 3^j * (n-j) // assuming T(0) = 0
Now we can find different upper bounds depending on how we much we want to think about it:
T(n) = Σ_(j=0..n-1) 3^j * (n-j)
< n * Σ_(j=0..n-1) 3^j
= n * (3^n - 1)
So T(n) = O(n*3^n).
You can also get a tighter bound by splitting the sum up into two parts:
T(n) = Σ_(j=0..n-1) 3^j * (n-j)
< n * Σ_(j=0..n-x) 3^j * (n-j) + x * Σ_(j=n-x..n-1) 3^j
= n (3^(n-x+1) - 1) + x * (3^n - 3^(n-x+1))
using x = log_3(n) you get T(n) = O(3^n * log(n)).
You can also approximate the sum Σ(n-i)3^i using an integral and get the exact complexity Θ(3^n).

Non-Linear Recurrence Relation

How can I find Nth term for this recurrence relation
F(n) = F(n-1) + F(n-2) + F(n-1)*F(n-2)
I have to find Nth term for this recurrence relation modulo 10^9+7.
I know how to find Nth term for linear recurrence relations but unable to proceed for this.
1<=N<=10^9
F(0) and F(1) are provided as an input.
There's a trick. Let G(n) = F(n) + 1. The equation
F(n) = F(n-1) + F(n-2) + F(n-1)*F(n-2)
becomes
G(n) - 1 = G(n-1) - 1 + G(n-2) - 1 + (G(n-1) - 1) * (G(n-2) - 1)
= G(n-1) - 1 + G(n-2) - 1 + G(n-1)*G(n-2) - G(n-1) - G(n-2) + 1
= G(n-1)*G(n-2) - 1,
so adding 1 to both sides,
G(n) = G(n-1)*G(n-2).
This is the multiplicative equivalent of the familiar Fibonacci recurrence. The solution is
G(n) = G(0)^Fib(n-1) * G(1)^Fib(n),
by analogy with the theory of linear recurrences (where Fib(-1) = 1 and Fib(0) = 0 and Fib(1) = 1), since
G(n-1)*G(n-2) = G(0)^Fib(n-2) * G(1)^Fib(n-1)
* G(0)^Fib(n-3) * G(1)^Fib(n-2)
= G(0)^Fib(n-1) * G(1)^Fib(n)
= G(n).
Hence,
F(n) = (F(0)+1)^Fib(n-1) * (F(1)+1)^Fib(n) - 1,
doing the Fib computations via the matrix power method mod p-1 per Fermat's little theorem and the exponentiation mod p.

Using induction to prove time complexity of functions

I want to find out the time complexity of this function by using induction f(n) = 0, if n = 0
f(n) = f(n − 1) + 2n − 1, if n ≥ 1 Im using a method call repeated substitution so then i found a close form for f(n)
f(n)= f(n − 1) + 2n − 1 =f(n-2)+4n-4 =f(n-3)+6n-8 .... =f(n-i)+2^in-d
and then by taking i=n i came out with f(n)=f(0)+2^(n+1)-d and can conclude that is has a time complexity of O(2^n) since f(0) and d are all constants.
however i found the answer should be O(n^2) and where did i do wrong
Your math was wrong.
f(n) = f(n - 1) + 2n - 1
f(n) = f(n - 2) + 4n - 4
f(n) = f(n - 3) + 6n - 9
...
f(n) = f(n - i) + 2i n - i^2
When i = n you have:
f(n) = f(n - n) + 2n n - n^2
= f(0) + (2 - 1) n^2
= n^2
Therefore, f(n) is O(n^2)
However you are mistaken. This is not the time-complexity of the function, which is O(n) since that's how many recursions it has, this is the function's order, which means how "quickly it diverges". O(n^2) means the function diverges at a quadratic rate.
I don't fully understand the question. The complexity of calculating the value is O(n), because you can just do the calculation starting from 0:
f(0) = 0
f(1) = 0 + 2*1 - 1 = 1
f(2) = 1 + 2*2 - 1 = 4
f(3) = 4 + 2*3 - 1 = 9
Actually, you probably get the idea . . . the nth value is n^2. I am guessing in the context of the problem that this is what they want the answer to be. However, to calculate it seems to be O(n).

Order by Recursion tree

I have tried determining the running time given by a recurrence relation, but my result is not correct.
Recurrence
T(n) = c + T(n-1) if n >= 1
= d if n = 0
My attempt
I constructed this recursion tree:
n
|
n-1
|
n-2
|
n-3
|
n-4
|
n-5
|
|
|
|
|
|
Till we get 1
Now at level i, the size of the sub problem should be, n-i
But at last we want a problem of size 1. Thus, at the last level, n-i=1 which gives, i=n-1.
So the depth of the tree becomes n-1 and the height becomes n-1+1= n.
Now the time required to solve this recursion = height of the tree*time required at each level which is :
n+(n-1)+(n-2)+(n-3)+(n-4)+(n-5)+ ...
==> (n+n+n+n+n+ ... )-(1+2+3+4+5+ ... )
==> n - (n(n+1)/2)
Now the time taken = n* ((n-n2)/2) which should give the order to be n2, but that is not the correct answer.
Now at level i, the size of the sub problem should be, n-i
Yes, that is correct. But you're assuming, that the runtime equals the sum of all the subproblem sizes. Just think about it, already summing the first two levels gives n + (n - 1) = 2n - 1, why would the problem size increase? Disclaimer: A bit handwavy and not an entirely accurate statement.
What the formula actually says
T(n) = c + T(n-1)
The formula says, solving it for some n takes the same time it takes to solve it for a problem size that is one less, plus an additional constant c: c + T(n - 1)
Another way to put the above statement is this: Given the problem takes some time t for a certain problem size, it will take t + c for a problem size, that is bigger by one.
We know, that at a problem size of n = 0, this takes time d. According to the second statement, for a size of one more, n = 1, it will take d + c. Applying our rule again, it thus takes d + c + c for n = 2. We conclude, that it must take d + n*c time for any n.
This is not a proof. To actually prove this, you must use induction as shown by amit.
A correct recursion tree
Your recursion tree only lists the problem size. That's pretty much useless, I'm afraid. Instead, you need to list the runtime for said problem size.
Every node in the tree corresponds to a certain problem size. What you write into that node is the additional time it takes for the problem size. I.e. you sum over all the descendants of a node plus the node itself to get the runtime for a certain problem size.
A graphical representation of such a tree would look like this
Tree Corresponding problem size
c n
|
c n - 1
|
c n - 2
|
c n - 3
.
.
.
|
c 2
|
c 1
|
d 0
Formalizing: As already mentioned, the label of a node is the additional runtime it takes to solve for that problem size, plus all its descendants. The uppermost node represents a problem size of n, bearing the label c because that's in addition to T(n-1), to which it is connected using a |.
In a formula, you would only write this relation: T(n) = c + T(n-1). Given that tree, you can see how this applies to every n>=1. You could write this down like this:
T(n) = c + T(n - 1) # This means, `c` plus the previous level
T(n - 1) = c + T(n - 2) # i.e. add the runtime of this one to the one above^
T(n - 2) = c + T(n - 3)
...
T(n - (n - 2)) = c + T(1)
T(n - (n - 1)) = c + T(0)
T(0) = d
You can now expand the terms from bottom to top:
T(n - (n - 1)) = c + T(0)
T(0) = d
T(n - (n - 2)) = c + T(1)
T(n - (n - 1)) = c + d
T(0) = d
T(n - (n - 3)) = c + T(2)
T(n - (n - 2)) = c + (c + d)
T(n - (n - 1)) = c + d
T(0) = d
T(n - (n - 4)) = c + T(3)
T(n - (n - 3)) = c + (2*c + d)
T(n - (n - 2)) = c + (c + d)
...
T(n) = c + T(n - 1)
T(n - 1) = c + ((n-2)c + d)
T(n) = c + (n-1)c + d = n*c + d
T(n - 1) = (n-1)c + d
Summing 1 to n
n+(n-1)+(n-2)+(n-3)+(n-4)+(n-5)+ ...
==> (n+n+n+n+n+ ... )-(1+2+3+4+5+ ... )
==> n - (n(n+1)/2)
From the first line to the second line, you have reduced your problem from summing 1 to n to, well, summing 1 to n-1. That's not very helpful, because you're stuck with the same problem.
I'm not sure what you did on the third line, but your transition from the first to the second is basically correct.
This would have been the correct formula:
T(n) = c + T(n-1)
= c + (c + T(n-2))
= ...
= c*i + T(n-i)
= ...
= c*n + T(0)
= c*n + d
If we assume c,d are constants - it gets you O(n)
To prove it mathematically - one can use mathematical induction
For each k < n assume T(n) = c*n + d
Base is T(0) = 0*n + d = d, which is correct for n < 1
T(n) = c + T(n-1) (*)
= c + (n-1)*c + d
= c*n + d
(*) is the induction hypothesis, and is valid since n-1 < n
The complexity would be O(n).
As you described the functions converts the problem for input n into problem for (n-1) by using a constant operation 'c'.
So moving down the recursion tree we will have in total n levels, and at each step we require some constant operation 'c'.
So there will be total c*n operations resulting into the complexity O(n).

How to solve: T(n) = T(n - 1) + n

I have the following worked out:
T(n) = T(n - 1) + n = O(n^2)
Now when I work this out I find that the bound is very loose. Have I done something wrong or is it just that way?
You need also a base case for your recurrence relation.
T(1) = c
T(n) = T(n-1) + n
To solve this, you can first guess a solution and then prove it works using induction.
T(n) = (n + 1) * n / 2 + c - 1
First the base case. When n = 1 this gives c as required.
For other n:
T(n)
= (n + 1) * n / 2 + c - 1
= ((n - 1) + 2) * n / 2 + c - 1
= ((n - 1) * n / 2) + (2 * n / 2) + c - 1
= (n * (n - 1) / 2) + c - 1) + (2 * n / 2)
= T(n - 1) + n
So the solution works.
To get the guess in the first place, notice that your recurrence relationship generates the triangular numbers when c = 1:
T(1) = 1:
*
T(2) = 3:
*
**
T(3) = 6:
*
**
***
T(4) = 10:
*
**
***
****
etc..
Intuitively a triangle is roughly half of a square, and in Big-O notation the constants can be ignored so O(n^2) is the expected result.
Think of it this way:
In each "iteration" of the recursion you do O(n) work.
Each iteration has n-1 work to do, until n = base case. (I'm assuming base case is O(n) work)
Therefore, assuming the base case is a constant independant of n, there are O(n) iterations of the recursion.
If you have n iterations of O(n) work each, O(n)*O(n) = O(n^2).
Your analysis is correct. If you'd like more info on this way of solving recursions, look into Recursion Trees. They are very intuitive compared to the other methods.
The solution is pretty easy for this one. You have to unroll the recursion:
T(n) = T(n-1) + n = T(n-2) + (n - 1) + n =
= T(n-3) + (n-2) + (n-1) + n = ... =
= T(0) + 1 + 2 + ... + (n-1) + n
You have arithmetic progression here and the sum is 1/2*n*(n-1). Technically you are missing the boundary condition here, but with any constant boundary condition you see that the recursion is O(n^2).
Looks about right, but will depend on the base case T(1). Assuming you will do n steps to get T(n) to T(0) and each time the n term is anywhere between 0 and n for an average of n/2 so n * n/2 = (n^2)/2 = O(n^2).

Resources