Solving a recurrence relation using Smoothness Rule - algorithm

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.

Related

Find formula to describe recursion in method

I am struggling with writing the formula that describes the recursive nature of the foo method.
The problem is that as far as I can tell, since every time n is divided with 2,
the binary tree formula should apply here.
This says that when in each call we divide the data we get a formula like this:
And then if we analyze for 2 so :
We get:
Which means that C(N) = log(N + 1), namely O(logN)
That all makes sense and seems to be the right choice for the foo method but it cant be because for
n = 8 I would get 3 + 1 iterations that are not n + 1 = 8 + 1 = 9 iterations
So here is your code:
void foo(int n) {
if (n == 1) System.out.println("Last line I print");
if (n > 1) {
System.out.println("I am printing one more line");
foo(n/2);
}
}
We can write a recurrence relation down for its runtime T as a function of the value of the parameter passed into it, n:
T(1) = a, a constant
T(n) = b + T(n/2), b constant, n > 1
We can write out some values of T(n) for various values of n to see if a pattern emerges:
n T(n)
---------
1 a
2 a + b
4 a + 2b
8 a + 3b
...
2^k a + kb
So for n = 2^k, T(n) = a + kb. We can solve for k in terms of n as follows:
n = 2^k <=> k = log(n)
Then we recover the expression T(n) = a + blog(n). We can verify this expression works easily:
a + blog(1) = a, as required
a + blog(n) = b + (a + blog(n/2))
= b + (a + b(log(n) - 1)
= b + a + blog(n) - b
= a + blog(n), as required
You can also use mathematical induction to do the same thing.

Summation of series 1 + (1+2+1) + (1+2+1+3+1+2+1)

The function is : F(n-1) n F(n-1)
Its a type of palindrome function called Zimmer Series.
The values would be : 1, 121, 1213121, ...
I want to figure the summation of the individual digits.
1 + (1+2+1) + (1+2+1+3+1+2+1) + ...
Any help is welcome.
Breaking this down into steps, we first find out a formula for the summation of a single value of the series and then we can find out the summation of said formula.
Expanding the definition you gave and manipulating it:
F(n) = n + 2F(n-1)
F(n) = n + 2(n-1) + 22(n-2) + 23(n-3) + ... + 2n-1
2F(n) = 2n + 22(n-1) + 23(n-2) + ... + 2n-1(2) + 2n
F(n) - 2F(n) = -F(n) = n - 2 - 22 - 23 - ... - 2n
From this and using the formula for Geometric Progression we can then get an expression for a single term of the series.
F(n) = (2n + 2n-1 + ... + 2) - n
= (2n+1 - 2) - n
Now we just have to work out the summation of this expression.
G(n) = Σ F(n) = Σ (2n+1 - 2 - n)
G(n) = (2n+2 - 22) - (2n) - (n(n+1)/2)
Simplifying this should hopefully give you the answer you seek!
G(n) = (2n+2 - (n(n+5)/2) - 22)
Trying this out on a few of the terms just to double check.
G(1) = (21+2 - (1(1+5)/2) - 22)
G(1) = 1
G(2) = (22+2 - (2(2+5)/2) - 22)
G(2) = 5 = 1 + (1 + 2 + 1)
G(3) = (23+2 - (3(3+5)/2) - 22)
G(3) = 16 = 1 + (1 + 2 + 1) + (1 + 2 + 1 + 3 + 1 + 2 + 1)
EDIT: Mark Dickinson is right, I misinterpreted the question, this solution is incorrect.
I think after the second term the sequence is of the form difference in Arithmetic Progression.
Let me show you how
Second Term = 1+2+1
Third Term = 1+2+1+3 + 1+2+1
Difference = 1+2+1+3 = 7
Third Term = 1+2+1+3+1+2+1
Fourth Term = 1+2+1+3+ 1+4+1+3 +1+2+1
Difference = 1+4+1+3 = 9
Fourth Term = 1+2+1+3+1+4+1+3+1+2+1
Fifth Term = 1+2+1+3+1+4+ 1+5+1+4 +1+3+1+2+1
Difference = 1+5+1+4 = 11
So as you can see the difference is in the arithmetic progression and you find the sum of the terms using the formula for the sum of numbers whose different are in Arithmetic Progression

Solving a recurrence relation for a recursive function

I need to create and solve a recurrence relation for the worst-case analysis for the following psuedocode. I am counting the number additions (not including the for loop counter) as my basic operation.
I am assuming n=2^k.
Here is the progress I have made...
Base Case:
T(n<=4) = 1
W(n)=W(2^k)=additions to calculate answer+additions in next recursion+addition in for loop
W(2^k) = 2 + W(2^(k-2)) + (2^k) - 2 = W(2^(k-2)) + (2^k)
I use back substitution and get the following recurrence relation...
for the jth recursive call
W(2^k) = W(2^(k-2j)) + (2^k) + sum(t=1,j,2^(k-2(t-1)))
I know that I can simplify this because I take W(2^(k-2j)) = W(4) and solve for j to see how many recursive steps the code takes.
In this case, j=(k/2) - 1. Reducing the recurrence gives me...
W(2^k) = 1 + (2^k) + sum(t=1,j,2^(k-2(t-1))).
Reducing the summation gives me...
W(2^k) = 1 + (2^k) + (2^k)*(2^2)*sum(t=1,j,2^(-2t)) or
W(n) = 1 + n + 4n*sum(t=1,j,2^(-2t))
What I cannot simplify is the summation. In lectures, we may have a summation of sum(i=1,n,2^i), which would be 2^(n+1)-1, but this one is different.
int function calc(int n) {
int num,answer;
if(n<=4) {return n+10;}
else {
num=calc(n/4);
answer=(num+num+10);
for(int i=2;i<=n-1;i++) {
answer=answer+answer;
}
return answer;
}
}
Any help would be appreciated. This assignment is due tonight. Thanks
The time complexity of the problem is T(n) = T(n/4) + n. The term n could mean \Theta(n). Hence, T(n) = n + n/4 + n/4^2 + ... + n/(4^log_4(n)) = n(1 + 1/4 + ... + 1/n) = \Theta(n). Notice that lim_{n\to \infty} 1 + 1/4 + ... + 1/4^log_4(n) = 4/3 which is a constant number.
T(n) = T(2^k) // by assumption
T(n) = T(n/4) + n // is the recurrence relation
T(2^k) = T(2^(k-2)) + (2^k) // rewriting
T(2^k) = T(2^(k-2j)) + (2^k)*SUM(i=0;j-1;(1/4)^i) // is the relation for iteration j
T(4) = T(2^(k-2j)) = 1 // when the recursion ends, base case reached, only 1 addition
2^2 = 2^(k-2j) // rewrite and remove T
2=k-2j // remove common base
j=(k/2)-1 // solve for jth iteration
Notice: cannot have decimal for iteration, so j=CEILING((k/2)-1)
SUM(i=0;j-1;(1/4)^i) = (1-(1/4)^j)/(1-(1/4))
For geometric sums and proof of transformation above, see wiki link below
Substituting j with CEILING((k/2)-1), the summation is...
SUM = (1-(1/4)^(CEILING((k/2)-1)))/(1-(1/4))
Finally, T(2^k) = 1 + (2^k)*SUM
In terms of the input n, T(n) = 1 + (n*SUM)
This formula is good for all k>=1
Testing several values...
k=1, T(2) = 1 + (2*0) = 1 // we know this is true because T(2) is a base case
k=2, T(4) = 1 + (4*0) = 1 // we know this is true because T(4) is a base case
k=3, T(8) = 1 + (8*1) = 9 // by recurrence formula, T(8) = T(2) + 8 = 9, true
k=4, T(16) = 1 + (16*1) = 17 // by recurrence formula, T(16) = T(4) + 16 = 17, true
k=5, T(32) = 1 + (32*1.25) = 41 // by recurrence formula, T(32) = T(8) + 32, T(8) = 9, 32+9=41 true
For geometric sums
https://en.wikipedia.org/wiki/Geometric_series

formula for the sum of n+n/2+n/3+...+n/n

so I got this algorithm I need to calculate its time complexity
which goes like
for i=1 to n do
k=i
while (k<=n) do
FLIP(A[k])
k = k + i
where A is an array of booleans, and FLIP is as it is, flipping the current value. therefore it's O(1).
Now I understand that the inner while loop should be called
n/1+n/2+n/3+...+n/n
If I'm correct, but is there a formula out there for such calculation?
pretty confused here
The more exact computation is T(n) \sum((n-i)/i) for i = 1 to n (because k is started from i). Hence, the final sum is n + n/2 + ... + n/n - n = n(1 + 1/2 + ... + 1/n) - n, approximately. We knew 1 + 1/2 + ... + 1/n = H(n) and H(n) = \Theta(\log(n)). Hence, T(n) = \Theta(n\log(n)). The -n has not any effect on the asymptotic computaional cost, as n = o(n\log(n)).
Lets say we want to calculate sum of this equation
n + n / 2 + n / 3 + ... + n / n
=> n ( 1 + 1 / 2 + 1 / 3 + ..... + 1 / n )
Then in bracket ( 1 + 1 / 2 + 1 / 3 + ... + 1 / n ) this is a well known Harmonic series and i am afraid there is no proven formula to calculate Harmonic series.
The given problem boils down to calculate below sum -Sum of harmonic series
Although this sum can't be calculated accurately, however you can still find asymptotic upper bound for this sum, which is approximately O(log(n)).
Hence answer to above problem will be - O(nlog(n))

Confused on recurrence and Big O

I know that
T(n) = T(n/2) + θ(1) can be result to O(Log N)
and my book said this is a case of Binary Search.
But, how do you know that? Is it just by the fact that Binary Search cuts the problem in half each time so it is O(Log N)?
And T(n) = 2T(n/2) + θ(1)
why is it that the result is O(N) and not O(Log N) when the algorithm divides in half each time as well.
Then T(n) = 2T(n/2) + θ(n)
can be result to O(N Log N)? I see the O(N) is from θ(n) and O(Log N) is from T(n/2)
I am really confused about how to determine the Big O of an algorithm that I don't even know how to word it properly. I hope my question is making sense.
Thanks in advance!
an intuitive solution for these problems is to see the result when unfolding the recursive formula:
Let's assume Theta(1) is actually 1 and Theta(n) is n, for simplicity
T(n) = T(n/2) + 1 = T(n/4) + 1 + 1 = T(n/8) + 1 + 1 + 1 = ... =
= T(0) + 1 + ... + 1 [logN times] = logn
T'(n) = 2T'(n/2) + 1 = 2(2T'(n/4) + 1) + 1 = 4T'(n/4) + 2 + 1 =
= 8T'(n/4) + 4 + 2 + 1 = ... = 2^(logn) + 2^(logn-1) + ... + 1 = n + n/2 + ... + 1 =
= 2n-1
T''(n) = 2T(n/2) + n = 2(2T''(n/2) + n/2) + n = 4T''(n/4) + 2* (n/2) + n =
= 8T''(n/8) + 4*n/4 + 2*n/2 + n = .... = n + n + .. + n [logn times] = nlogn
To formally prove these equations, you should use induction. Assume T(n/2) = X, and using it - prove T(n) = Y, as expected.
For example, for the first formula [T(n) = T(n/2) + 1] - and assume base is T(1) = 0
Base trivially holds for n = 1
Assume T(n) <= logn for any k <= n-1, and prove it for k = n
T(n) = T(n/2) + 1 <= (induction hypothesis) log(n/2) + 1 = log(n/2) + log(2) = log(n/2*2) = log(n)
I find an easy way to understand these is to consider the time the algorithm spends on each step of the recurrence, and then add them up to find the total time. First, let's consider
T(n) = T(n/2) + O(1)
where n=64. Let's add up how much the algorithm takes at each step:
T(64) = T(32) + 1 ... 1 so far
T(32) = T(16) + 1 ... 2 so far
T(16) = T(08) + 1 ... 3 so far
T(08) = T(04) + 1 ... 4 so far
T(04) = T(02) + 1 ... 5 so far
T(02) = T(01) + 1 ... 6 so far
T(01) = 1 ... 7 total
So, we can see that the algorithm took '1' time at each step. And, since each step divides the input in half, the total work is the number of times the algorithm had to divide the input in two... which is log2 n.
Next, let's consider the case where
T(n) = 2T(n/2) + O(1)
However, to make things simpler, we'll build up from the base case T(1) = 1.
T(01) = 1 ... 1 so far
now we have to do T(01) twice and then add one, so
T(02) = 2T(01) + 1 ... (1*2)+1 = 3
now we have to do T(02) twice, and then add one, so
T(04) = 2T(02) + 1 ... (3*2)+1 = 7
T(08) = 2T(04) + 1 ... (7*2)+1 = 15
T(16) = 2T(08) + 1 ... (15*2)+1 = 31
T(32) = 2T(16) + 1 ... (32*2)+1 = 63
T(64) = 2T(32) + 1 ... (65*2)+1 = 127
So we can see that here the algorithm has done 127 work - which is equal to the input multiplied by a constant (2) and plus a constant (-1), which is O(n). Basically this recursion corresponds to the infinite sequence (1 + 1/2 + 1/4 + 1/8 + 1/16) which sums to 2.
Try using this method on T(n) = 2T(n/2) + n and see if it makes more sense to you.
One visual solution to find the T(n) for a recursive equation is to sketch it with a tree then:
T(n) = number of nodes * time specified on each node.
In your case T(n) = 2T(n/2) + 1
I write the one in the node itself and expand it to two node T(n/2)
Note T(n/2) = 2T(n/4) + 1, and again I do the same for it.
T(n) + 1
/ \
T(n/2)+1 T(n/2)+1
/ \ / \
T(n/4)+1 T(n/4)+1 T(n/4)+1 T(n/4)+1
... ... .. .. .. .. .. ..
T(1) T(1) .......... ............T(1)
In this tree the number of nodes equals
2*height of tree = 2*log(n) = n
Then T(n) = n * 1 = n = O(n)

Resources