analyzing complexity of recursive algorithm with uneven division - algorithm

I was asked to analyze the time complexity of the following recursive equation using the iterative method:
T(n)=T(n/3)+T(2n/3)+n^2.
T(1)=1
when I try to expand the equation it blows up and I can't really keep track of all the recursive "calls" and constants.
This is caused by the uneven division of the data (1\3 - 2\3).
Is there an easier way to solve this using the iterative method?
Many thanks.

Here is a paper that shows the analysis of a similiar formula: T(n)=T(n/3)+T(2n/3)+n
One way to make it iterative will require using a method similar to how parsers\compilers work
Applying your formula: T(n)=T(n/3)+T(2n/3)+n^2 with n = 1..9 yields
T(0) = 0
T(1) = T(1/3) + T(2/3) + 1
T(2) = T(2/3) + T(4/3) + 4
T(3) = T(1) + T(2) + 9
T(4) = T(4/3) + T(8/3) + 16
T(5) = T(5/3) + T(10/3) + 25
T(6) = T(2) + T(4) + 36
T(7) = T(7/3) + T(14/3) + 49
T(8) = T(8/3) + T(16/3) + 64
T(9) = T(3) + T(6) + 91
T(3m) = T(m) + T(2m) + 9m^2
.. Maybe this can give you some hints

What helps here is to not multiply out any of the numbers, but write everything in terms of powers. Doing that all by hand, I got the following for the first few expansions:
T(n) = T((1/3)n) + T((2/3)n) + n^2
= T((1/3^2)n)
+ 2T((2/3^2)n)
+ T((2^2/3^2)n)
+ [n^2] #constants from the first expansion
+ [((1/3)n)^2 + ((2/3)n)^2] #constants from the second expansion
= T((1/3^3)n)
+ 3T((2/3^3)n)
+ 3T((2^2/3^3)n)
+ T((2^3/3^3)n)
+ [n^2]
+ [((1/3)n)^2 + ((2/3)n)^2]
+ [((1/3^2)n)^2 + ((2/3^2)n)^2 + ((2^2/3^2)n)^2] #constants from 3rd expansion
It's a bit hard to tell, but what seems to happen is that you get the binomial coefficients going for the Ts, where the xth expansion looks like this:
T(n) = sum((x choose i) * T(((2^i)/(3^x))n), i from 0 to x)
+ constants
At each step, the additional constants that are added at expansion x are the arguments to T from expansion x-1, squared, since they all end up getting squared thanks to the n^2. So all the new constants at a given expansion y are equal to:
NewConsts(y) = sum(((y - 1) choose i) * (((2^i)/(3^(y-1)))*n)^2, i from 0 to y - 1)
And all the constants at expansion x are equal to
n^2 + sum(NewConsts(y), y from 1 to x)
So, assuming all the above is correct, which I'm not 100% sure on, I guess you have to figure out when the constants stop mattering - that is, for what x is ((2^x / 3^x) * n)^2) equal to 0 - and your answer is the sum of all of those constants...

It seems to be O(n^2) if I haven't missed anything...
First of all T grows monotonously (for several first values you can check this manually, for the rest it's by induction - if a function is monotonous in [1..10], then it will be monotonous on [1..15] and so on).
T(n)=T(n/3)+T(2n/3)+n^2<=2T(2n/3)+n^2
T(n)<=n^2+2*(2n/3)^2+4*(4n/9)^2+...
=sum[k=0..log3(n)]((8/9)^k*n^2)
=n^2*sum[k=0..log3(n)](8/9)^k
<=n^2*sum[k=0..inf](8/9)^k
<=C*n^2

Related

Solving a recurrence relation using Smoothness Rule

Consider this recurrence relation: x(n) = x(n/2) + n, for n > 1 and x(1) = 0.
Now here the method of back substitution will struggle for values of n not powers of 2, so it is best known here is to use the smoothness rule to solve this types of questions, and when we use the smoothness rule, where we will solve for n = 2^k (for n = values powers of 2) we will have a solution of x(n) = 2n - 1.
However, if we use the method of backward substitution, this recurrence relation will have a solution!
x(n) = x(n/2) + n = x(n/4) + n/2 + n = x(n/8) + n/4 + n/2 + n = x(n/16) + n/8 + n/4 + n/2 + n = ....
where the pattern is
x(n) = x(n/i) + n/(i/2) + n/(i/4) + n/(i/8) + n/(i/16) + ...
which will stop when n = 1 (i.e when i = n) and in this case
x(n) = x(n/n) + n/(n/2) + n/(n/4) + n/(n/8) + n/(n/16) + ... = 1 + 2 + 4 + 8 + 16 + ... = 2^(n+1) - 1
which is two different answers!
So please I am so confused here because in the textbook (Introduction to Analysis and Design of Algorithms by Anany Levitin) it is mention that we should use here the smoothness rule, but as you can see I have solved it exactly by the method of backward substitution where the method was expected here to struggle but nothing has happened!
The transition 1 + 2 + 4 + 8 + 16 + ... = 2^(n+1) - 1 is false.
That is since the number of elements in the left series is log n so the sum is 2^(log n + 1) - 1, which is exactly 2n - 1.
The reason there are log n elements is that n/(2^i) = 1 (the last element of the series is 1) when i = log n.

How to solve T(n) = T(n-3)+n^2 using iteration?

How can I solve T(n) = T(n-3)+n^2 using iteration?By master theorem answer is O(n^3) but I am having trouble solving it by iteration.
By direct resolution of the recurrence:
This is a linear recurrence of the first order. We first solve the homogeneous part,
T(n) = T(n - 3)
which is solved by a constant (more precisely three constants as three intertwined sequences form the solution).
Now for the non-homogeneous part, we use the Ansatz T(n) = an³ + bn² + cn + d, because we know that the difference of two cubic polynomials is a quadratic one.
Then
a(n³ - (n-3)³) + b(n² - (n-3)²) + c(n - (n-3)) = 9an² + 3(-9a + 2b)n + 3(9a - 3b + c) = n²
gives
a = 1/9, b = 1/2, c = 1/2.
Finally
T(n) = (2n³ + 9n² + 9n)/18 + T(0)
and similarly for the two other sequences.
Just try to expand the equation:
T(n) = n^2 + (n-3)^2 + (n-6)^2 + ... + 1 = \Theta(n^3)
T(3) = T(0) + 3²
T(6) = T(3) + 6² = T(0) + 3² + 6²
T(9) = T(6) + 9² = T(0) + 3² + 6² + 9²
...
More generally, T(3N) is the sum of T(0) and nine times the sum of the squared naturals up to N. The well-known Faulhaber formula justifies O(N³).
Similar results hold for T(3N+1) and T(3N+2).

Basic randomized algorithm recurrence

I'm having trouble fully understanding how to write the recurrence for the expected running time of a randomized algorithm.
I believe I'm doing it correctly, but if someone could look over it, that'd be a huge help.
Here's the pseudocode for the algorithm:
printIntegers(A, n) // an array A of integers is the input, with n integers
if A.length > 0
for i = 1 to n
print A[i]
randInt = rand(1, 10)
if randInt != 10
return
else
printIntegers(A, n-1)
The only random part is the random generator between 1 and 10. I'm trying to understand how that would translate in the recurrence.
I'm thinking:
T(n) = O(n) if a != 10 probability = 9/10
T(n-1) + O(n) a = 10 = 1/10
T(n-2) + O(n)
....
T(0) + O(n)
This makes sense in my head, and then the expected running time would be O(n). Am I approaching this correctly?
Note that the initial condition should use n in the check, not A.length since the latter is not changing in the recursion.
The expected number of times the recursion will be called is 0.1. The expectation is the same as the probability the recursion will be called. In the current case, if the random number generator is truly random, the number 10 will appear 1/10 of the times. Likewise, the expected number of times there will be no recursion is 0.9. But the O(n) appears in both the cases, so the equation will be, when considering expected values:
T(n) = (0.9 + 0.1) * O(n) + 0.1 * T(n-1)
= O(n) + 0.1 * T(n-1)
= O(n) + 0.1 * (O(n-1) + 0.1 * T(n-2))
= O(n) + 0.1 * O(n-1) + 0.1^2 * O(n-2) +...
= O(n) * (0.1 + 0.1^2 +...+0.1^(n-1)) + 0.1^(n-1) * T(1)
= O(n) * (1 - 0.1^n)/0.9 + K
The above is O(n * (1 - 0.9^n)/0.9) which is essentially the same as O(n) depending upon your accuracy needs.
First note that:
T(n) = n + (n-1)/10 + (n-2)/10^2 + ... + 1/10^{n-1}
Then, bounding T(n) above:
T(n) = n + (n-1)/10 + (n-2)/10^2 + ... + 1/10^{n-1}
< n + n/10 + n/10^2 + ... + n/10^{n-1}
= n(1 + 1/10 + ... + 1/10^{n-1})
< n(1 + 1/10 + 1/10^2 + ...)
= n/(1 - 1/10) = 10n/9
and bounding it below:
T(n) = n + (n-1)/10 + (n-2)/10^2 + ... + 1/10^{n-1}
> n
So n < T(n) < 10n/9 and T(n) is Theta(n).

Time complexity of the program using recurrence relation

This program calculate fibonacci numbers. I want to find out its time complexity using recurrence relation.
Fib(n)
if n<=1
return n
else
x= Fib(n-1)
y= Fib(n-2)
return x+y
The recurrence equation for this program is
T(n)=T(n-1)+T(n-2)+c
I tried to expend it , but couldn't find the solution.
=2T(n-1)+T(n-3)+c+c
=3T(n-3)+2T(n-4)+c+c+3c
=5T(n-4)+3T(n-3)+c+c+3c+5c
-------------------------
-------------------------
-------------------------
You need to think about how many calls you make to your function.
Each call makes 2, so it makes a binary tree:
n
(n-1)--------------(n-2)
(n-2)--(n-3)------(n-3)---(n-4)
and so on.
Consider the level of the tree when you first reach 1 and ignore everything below.
This happens on level n/2 (since the lowest number of each level is the rightmost and it always decreases by 2).
It's clear that the nodes on each level up to n/2 are always twice as many as on the previous level.
Thus the total number of nodes is 1 + 2 + 2^2 + ... + 2^(n/2) = 2^(n/2+1) - 1 = O(2^(n/2))
This means that the time complexity is at least exponential.
You can probably compute it even more accurately, but for all practical purposes this should be enough to avoid this implementation.
The given recurrence relation is,
T(n) = T(n-1) + T(n-2) + c ------ 1
T(n-1)= T(n-2) + T(n-3) + c ------ 2
1-2 -> T(n) = 2T(n-1) - T(n-3) ----- 3
T(n) - 2T(n-1) + T(n-3) = 0 ----- 4
The characteristic equation of 4 is x3 - 2x2 + 1 = 0 ---- 5
Solve equation 5,
The solutions are x = 1, x = (1 + √5)/2 and x = (1 −√5)/2
There for the general solution is,
Tn = a((1 + √5)/2)n + b((1 - √5)/2)n + c . 1n
There for Tn = a((1 + √5)/2)n + b((1 - √5)/2)n + c
Let us assume T(0) = 0, from equation 1 we get T(1) = c and T(2) = 2c
There for,
T(0) = a + b + c = 0 ---- 6
T(1) = a((1 + √5)/2) + b((1 - √5)/2) + c = c
There for a((1 + √5)/2) + b((1 - √5)/2) = 0 ----- 7
T(2) = a((1 + √5)/2)2 + b((1 - √5)/2)2 + c = 2c
There for a((1 + √5)/2)2 + b((1 - √5)/2)2 = c ---- 8
solve 6, 7 and 8, to get the values of a, b and c.
The general solution is,
Tn = a((1 + √5)/2)n + b((1 - √5)/2)n + c
since (1 + √5)/2 < 2,
T(n) = O(2n).
The thing to note about your recurrence relation is that it's the same as the Fibonacci recurrence itself. This means that you're doing c units of work times whatever Fibonacci number you're calculating. You can see it yourself from the first few steps that you computed. The c's start growing like the Fibonacci numbers.
Basically your recurrence comes down to O(Fib(n)). Fibonacci numbers are exponential in n, so you're going to do exponential work.
A better way to do this is to remember one of the numbers. Like this:
Fib(n):
if n <= 2:
return 1,0
else:
x,y = Fib(n-1)
return x+y,x
So when you call Fib(n), you're getting two values, Fib(n) and Fib(n-1). That extra x that you return "remembers" Fib(n-2) so you don't have to compute it twice. This recurrence comes down to T(n) = T(n-1) + c, which is O(n).
Once you have that, you can reduce this to a nice little for loop:
x = 1, y = 0
for i from 3 to n:
x,y = x+y,x

Solving a recurrence relation

I'm not sure if this is the right place to post this, but the problem actually belongs to a programming assignment. This recursion is something I probably should know how to solve but Im having a bit of trouble with it.
Solve the recursion:
T(0) = 2;
T(n) = T(n-1) + 2;
Solution:
T(n) = 2(n+1)
Could someone please show me how they got to that solution?
Please not that its not the main part of the assignment to solve this particular problem.
You have to figure out what is solution and then you can use induction, to prove it.
To figure solution is simple.
Value is previous value + 2.
2, 2+2, 2+2+2, 2+2+2+2, 2+2+2+2+2, ...
Use induction to prove:
T(0) = 2
T(n) = T(n-1) + 2;
Solution
T(n) = 2(n+1)
Proof:
T(n) = T(n-1) + 2 => 2((n-1)+1) + 2 = 2(n+1)
Check for n=0
2(0+1)=2
End of proof
Try writing out the first few values - it should then be obvious.
Take T(5):
T(5)
|
+-> T(4) + 2
|
+-> T(3) + 2
|
+-> T(2) + 2
|
+-> T(1) + 2
|
+-> T(0) + 2
|
+-> 2
Now count the number of 2's that are added together for T(5).
Then try to figure out how many 2's would be added for T(n).
It's an arithmetic progression with ratio common difference 2.
The first term is T[0] = 2 and the ratio common difference is r = 2 so the n + 1th term (n + 1th because there are n + 1 numbers in 0, 1, 2, ..., n) is T[0] + r*(n + 1 - 1) = 2 + 2*n = 2*(n + 1).
No guessing required, just recognize it as an arithmetic progression.
Each time n decreases by one, 2 is added. This gives a variable term of 2n. Since T(0) is fixed at 2, this gives a constant term of 2. Adding them together gives 2n + 2, or 2(n + 1).
I'd solve it as follows:
Assume that T(n) = a*n + b for some a and b.
T(0) = 2. So a * 0 + b = 2, thus b = 2.
T(n) = T(n-1) + 2, so
a * n + b = (a * (n-1) + b) + 2 consequently
a * n + b = a * n - a + b + 2 and
0 = - a + 2, thus a = 2.
So we have T(n) = 2 * n + 2 = 2 (n+1).
This one is pretty straightforward to solve by hand as the other answers point out, but in case it's ever useful, Mathematica is pretty good solving recurrence relations like this.
Evaluating
RSolve[{T[0] == 2, T[n] == T[n-1] + 2}, T[n], n]
returns
{{T[n] -> 2 (1 + n)}}
It can, for example, find the closed form of the nth Fibonacci number as well:
RSolve[{F[1] == 1, F[2] == 1, F[n] == F[n-1] + F[n-2]}, F[n], n] //FunctionExpand
returns
{{F[n] -> (((1 + Sqrt[5])/2)^n - (2/(1 + Sqrt[5]))^n*Cos[n*Pi])/Sqrt[5]}}

Resources