Here's the code:
class qual
{
public static int fibonacci(int n)
{
if (n == 0 || n == 1)
{
return 1;
}
else
{
return fibonacci(n-1) + fibonacci(n-2);
}
}
public static void main(String[] arg)
{
System.out.println(fibonacci(5));
}
}
The output was 8.
The output should be 8 but when I look at this I think it should be 7 ((5-1) +(5-2)).
Why was the output 8? I think the reasoning behind getting 8 will make recursion maybe stop being confusing for me.
Let's treat this like algebra, I'll write f(n) instead of fibonacci(n) to save space:
f(5) = f(4) + f(3)
f(5) = f(3) + f(2) + f(2) + f(1)
f(5) = f(2) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = f(1) + f(0) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
Because it's a recursive call, so each call where the argument is not 0 or 1 calls it again.
fibonacci(7)
-> fibonacci(6) // recursively calls itself with (7-1)
-> fibonacci(5) // recursively calls itself with (6-1)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(4) // recursively calls itself with (6-2)
...
-> fibonacci(5) // recursively calls itself with (7-2)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(3) // recursively calls itself with (5-2)
...
and so on.
Think about the logic like this, and you should be able to work out what it actually returns to the initial caller.
It's returning fibonacci(n-1), not n-1. When you call this with 5, you get:
return fib(4) + fib(3);
fib(4) returns:
return fib(3) + fib(2);
fib(3) returns:
return fib(2) + fib(1);
fib(2) returns:
return fib(1) + fib(0);
As soon as you reach fib(1) or fib(0), you return 1;
Working backwards, fib(2) returns 2:
return 1 /*fib(1)*/ + 1 /*fib(0)*/;
By the same logic, fib(3) returns 2 + 1, or 3. Fib(4) returns 3 + 2, or 5. Fib(5) therefor returns 5 + 3, which is your 8.
Perhaps this illustration adapted from the Structure and Interpretation of Computer Programs (SICP, or the Wizard book) will help:
Going off on a tangent, SICP is a fantastically deep though at times difficult introduction to programming. Since it uses Lisp (rather, Scheme) as its teaching language, recursion is used throughout. Even iterative processes in Lisp are based on recursive calls:
(define (factorial n)
(define (fact-iter n product)
(if (> n 1)
(fact-iter (- n 1) (* product n))
product
) )
(fact-iter n 1)
)
(factorial 5)
; returns 120
is actually iterative. Notes: car returns the head of a list, while cdr returns the tail. Operators use prefix notation; (- a b) is "a - b", (* a b) is "a * b".
Here's what your Fibonacci program looks like in Scheme:
(define (fibonacci n)
(if (or (= n 1) (= n 2))
1
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))
)
It's not ((5-1) + (5-2)), but rather (finonacci(5-1) + fibonacci(5-2))
And finonacci(5-1) reduces to fibonacci(4), which becomes (finonacci(4-1) + fibonacci(4-2)), etc.
return fibonacci (n-1) + fibonacci (n-2);
That's actually not just doing (n-1) + (n-2), it's recursively calling the fibonnacci function again.
So it's doing fibonacci (4) + fibonacci (3). That fib(4) is then evaluated to be fib(3) + fib(2), so it ends up returning fib (3) + fib (2) + fib (3). Again, each of those fib(3)'s are actually fib (2) + fib (1), and so on. It keeps breaking down like that, until it hits
if (n == 0 || n == 1)
so it ends up being a bunch of fib (1) + fib (0) + fib (1)..., which is 1 + 1 + 1..., which will end up as 8 if you actually break it all the way down.
I haven't seen this approach yet. Imagine you are storing results and building it up, where f[i] is the result of calling fibonacci(i). 0 and 1 are base cases, and the rest build on it:
f[0] = 1
f[1] = 1
f[2] = f[1] + f[0] = 1 + 1 = 2
f[3] = f[2] + f[1] = 2 + 1 = 3
f[4] = f[3] + f[2] = 3 + 2 = 5
f[5] = f[4] + f[3] = 5 + 3 = 8
The result of the function is not (5 - 1) + (5 - 2), but fibonacci( 5 - 1 ) + fibonacci( 5 - 2 ) or fibonacci( 4 ) + fibonacci( 3 ), which is 5 + 3. The sequence is:
1 1 2 3 5 8
0 1 2 3 4 5
Recursion is actually closely related to the mathematical concept of proof by induction -- and in fact the Fibonacci sequence is recursively defined, so on some level you have to already think in recursive terms to understand how it works.
To better understand the code, you can apply a beta reduction -- that is, replace each function call with the body of the function itself.
If fibonacci(n) translates to fibonacci(n - 1) + fibonacci(n - 2) then:
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(5) = (fibonacci(3) + fibonacci(2)) + (fibonacci(2) + fibonacci(1))
It's easy to see that this would go on forever, unless we made a special case. Here, we know that fibonacci(1) translates to 1, and fibonacci(0) also translates to 1. So we keep beta-reducing until all we have left are ones, which looks like:
fibonacci(5) = ((1 + 1) + (1 + (1 + 1))) + ((1 + 1) + 1)
Therefore:
fibonacci(5) = 8
The first fibonacci number are 1,1,2,3,5,8,... any other numbers would be unexpected.
Related
I was implementing a very simple recursive method to multiply two numbers together. I am very a hard time understanding the basics of recursion.
Is anyone able to explain to me (Line-by-line if possible) how this code works? I am especially confused about the base case is written to return 0 when in reality the actual multiplication is returned instead.
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n; //Recursive Case - Decrements m, while adding n
}
Thanks for any help
I will try to make this answer beginner friendly. First I will answer this part of your question:
I am especially confused about the base case is written to return 0
when in reality the actual multiplication is returned instead.
The value returned in the base case depends on how you are implementing your algorithm. Here in order to calculate n*m, we extend this multiplication to addition. A few examples will make this more clear.
2*3 = 2 + 2 + 2 + 0
4*1 = 4 + 0
5*5 = 5 + 5 + 5 + 5 + 5 + 0
n*m = n + n + n + ... + (m times) + 0
That is why we return 0 in the base case, we have to stop the recursion without making any change in the result and that is only possible if we add 0.
Here is the working of this program:
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n;
Let us take n = 4 and m = 3.
Our first call to the method is multiply(4, 3). We then proceed further, the base condition is false so we skip that.
We then get to this part: return multiply(n, m - 1) + n. We make another call to the same function. multiple(4, 2). Again we skip the base case. Here is a table:
multiply(4, 3) -> return multiply (4, 2) + 4
multiple(4, 2) -> return multiply (4, 1) + 4
multiple(4, 1) -> return multiply (4, 0) + 4
multiple(4, 0) -> 0
On substituting the returned values we get,
multiple(4, 3) -> return 0 + 4 + 4 + 4
multiple(4, 2) -> return 0 + 4 + 4
multiple(4, 1) -> return 0 + 4
multiple(4, 0) -> return 0
If our first call is multiply(n, m), then the end returned value is:
multiply (n, m) -> return 0 + n + n + n + ... + (m times)
I hope I have helped you. Try to construct a similar relation like this on your own and you will understand it better. Here is a link on further explanation on recursion:
https://www.geeksforgeeks.org/recursion
I don't understand how this exercise return the number's square. In particular I don't understand the sixth line in which there is return statement and after this "+2*x-1". What is the program behavior in that call?
public class Es {
public static int RecCalc(int x) {
if (x==0) {
return 0;
}else {
return RecCalc(x - 1) + 2 * x - 1;
}
}
public static void main(String[] args) {
System.out.println(RecCalc(3));
}
}
We can see how this works with a little algebra:
(x-1)² + 2x - 1
== x² - 2x + 1 + 2x - 1
== x²
If you are unfamiliar with the formula for (x + y)² then you can do (x-1)² by writing it as (x-1)*(x-1) and using the FOIL method or the distributive property. This is left as an exercise for the reader.
Let's step through, one call at a time.
The first call to kick it all off is:
RecCalc(3);
In Java, the return statement will take everything up to the semi-colon.
So, return 3 + 2 will return 5 to the caller.
RecCalc(3) will result in calling:
RecCalc(2) + 2*3 -1;
RecCalc(2) will result in calling:
RecCalc(1) + 2*2 -1;
RecCalc(1) will result in calling:
RecCalc(0) + 2*1 - 1;
RecCalc(0) will return 0.
Now we can work our way back up the call stack.
RecCalc(0) == 0
RecCalc(1) == RecCalc(0) + 2*1 -1 == (0) + 2*1 -1 == 1
RecCalc(2) == RecCalc(1) + 2*2 -1 == (1) + 2*2 -1 == 4
RecCalc(3) == RecCalc(2) + 2*3 -1 == (4) + 2*3 -1 == 9
This doesn't explain the math, but explains the recursion.
Let's look at the math.
As explained by #CodeApprentice, x² = (x-1)² + 2x -1
The real trick to this whole recursive scheme is the (x-1)².
We know that for x = 4, we can use (x-1)² plus some other junk to get the answer.
But that's just the square of 3 plus some other junk!
Now, to get the square of 3, we know that 3² = (x-1)² plus junk.
But that's just the square of 2 plus some other junk!
And so, we work our way down until we get to a trivial answer, where we return 0. (In fact, you could also return 1 for x=1).
I hope that explains it!
If you have 4 things, you can make a square with side 2:
xx
xx
If you want to make a square with side 3, you need 9 things: add 2 things on each of the side and bottom, plus 1 for the corner:
xx.
xx.
..+
Or, to put it another way, add 3 things on each of the side and bottom, take away 1 for the corner.
Generalizing, if you have a square of side length (n-1), to make a square of side length (n), you have to add on 2 lots of (n-1) things, plus one; or 2 lots of (n) things, take away one.
Hence:
number of things in a square of side length n
= (number of things in a square of side length (n-1))
+ 2 * (n-1) + 1
= (number of things in a square of side length (n-1))
+ 2 * n - 1
Perhaps if you put in a print statement it will help.
public static void main(String[] args) {
System.out.println(RecCalc(5));
}
public static int RecCalc(int x) {
if (x == 0) {
return 0;
} else {
int v = RecCalc(x - 1) + 2 * x - 1;
System.out.println((x-1) + " " + (2*x) + " " + (-1));
return v;
}
}
Prints
0 2 -1
1 4 -1
2 6 -1
3 8 -1
4 10 -1
25
Notice that the value of the sum of the last two columns in each line is an odd number. And the sum of any number of consecutive odd numbers starting with 1 is a perfect square. So essentially, this method just sums up the first x odd numbers.
I am having some problems understanding stacks and order of operations in java. If I had the following:
operation(7, 2)
public int operation(int x, int y) {
if (x == y)
return 0;
else
return operation(x – 1, y) + 2;
}
What would be the result? I am being told that it should be a single number result but I don't understand how (x – 1, y) + 2 can be single number. I have gotten it to:
(x – 1, y) + 2
(7 - 2, 2) + 2
(5, 2) + 2
But I don't understand the method for adding the 2 at the end. Wouldn't this need to return both values separated by a comma?
Wouldn't this need to return both values separated by a comma?
Nope.
operation(x – 1, y) + 2 is a recursive function.
operation(7 - 1, 2) + 2 => operation(6, 2) + 2 This calls the operation function with arguments 6 and 2 (similar to how you did the initial call). This call will eventually end up with a number to which 2 is added and returned.
Taking a smaller number for better visualization operation(4, 2)
operation(4, 2) -> return operation(3, 2) + 2
operation(3, 2) -> return operation(2, 2) + 2
operation(2, 2) -> return 0 (the base case)
.. stack unwinds
operation(3, 2) -> return 0 + 2
operation(4, 2) -> return 2 + 2
operatation(7, 2) returns -> 8 + 2 = 10
operatation(6, 2) returns -> 6 + 2 = 8
operatation(5, 2) returns -> 4 + 2 = 6
operatation(4, 2) returns -> 2 + 2 = 4
operatation(3, 2) returns -> 0 + 2 = 2
operatation(2, 2) returns -> 0
The recursive calls will be made till the x and y values equal, in that case operation returns 0. The return value is then added to 2 and returned to caller i.e. 0 + 2 = 2 and so on, till the first caller is returned. Hence the answer is 10.
This ends up being roughly equivalent to a for loop, actually. This code has the exact same result as operation(7, 2):
int equivOfOperation = 0;
for (int i = 2; i < 7; i++)
{
equivOfOperation += 2;
}
The recursive function will end up doing the equivalent of
for (int i = y; i < x; i++)
assuming, of course, that y < x. (In this case, operation would end up with infinite recursion).
Since several of the other answers have already shown the trace of the recursion, I won't repeat that here, but you might want to walk through their traces and convince yourself of this having the same effect as a for loop.
how do i get the max and min number of nodes in an AVL tree when given the height of 8.
i can't seem to be able to trace it out properly from the formula f(8)=f(7)+f(6)+1
2*f(6)+f(5)+2
2*[f(5)+f(4)+1]+f(5)+2
3*f(5)+2*f4+4
3*[f(4)+f(3)+1]+2*f(4)+4
5*f(4)+3*f(3)+7
5*[f(3)+f(2)+1]+3*f(3)+7
8*f(3)+5*f(2)+12
8*[f(2)+f(1)+1]+5*f(2)+12
13*f(2)+8*f(1)+20
13*[f(1)+f(0)+1]+8*f(1)+20
21*f(1)+13*f(0)+33=54 whereas answer is 88 is the minimum
For every node in AVL tree we know that the depths of the left and the right subtree differs by at most 1 (this is given by definition).
From that, the next step is quite obvious : we take the minimum trees of depths N and N - 1 and place them as subtrees for a new root. It's clear that the AVL rules still hold and that the tree is contains as little nodes as possible (obvious from the induction base case).
From that, we've got the recursion formula : minnodes(depth) = 1 + minnodes(depth-1) + minnodes(depth - 2). That's a simple recursive equation, Wolfram Alpha can solve that for you (link).
The second case is trivial - a perfect binary tree of depth h contains as many nodes as possible for the depth given and trivially satisfies the AVL conditions.
You miscalculated a step somewhere, looks like near the end:
f(0) = 1
f(1) = 2
f(2) = f(1) + f(0) + 1 = 4
f(3) = f(2) + f(1) + 1 = 4 + 2 + 1 = 7
f(4) = f(3) + f(2) + 1 = 7 + 4 + 1 = 12
f(5) = f(4) + f(3) + 1 = 12 + 7 + 1 = 20
f(6) = f(5) + f(4) + 1 = 20 + 12 + 1 = 34
f(7) = f(6) + f(5) + 1 = 34 + 20 + 1 = 55
f(8) = f(7) + f(6) + 1 = 55 + 34 + 1 = 88
And if you don't believe it, you can always cook up a quick snippet to check:
#Test
public void testGetMax() {
assertEquals(88, getMax(8));
}
int getMax(int x) {
switch (x) {
case 0:
return 1;
case 1:
return 2;
default:
return getMax(x - 1) + getMax(x - 2) + 1;
}
}
I'm preparing for a java programming exam that's coming up in a few days and I've been tryna get my head around this:
The initial starting value of int num is 8
public int func1(int num)
{
if(num <=1) return 1;
return num + func1 (num - 3);
}
How do you go through through the return num + func1 (num - 3) part?
I don't get how that line of code works
I hope this will help you understand recursion.
return 8 + func1(5)
return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
and finally returns like
return 8 + 5 + 3
return 8 + 8
return 16
Easiest way to understand recursion is
Assume that the whole public int func1(int num) is inserted in the return
so ur function returns somewhat in this way
return 8 + func1((8) - 3) // i.e return 8 + func1(5)
return 8 + 5 + func1((5) - 3) // i.e return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1((2) - 3) // i.e return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
So total will be 16
Just trace through it the exact same as for any other method call. It's just calling itself which is another way to do a loop.
i.e.
func1(8)
calls func1(8-3)
calls func1(5-3)
calls func1(2-3)
returns 1 as -1 < 1
returns 2+1
returns 5+3
returns 8+8
So the final result is 16.
"The only way to understand recursion is to understand recursion".
Now seriously, you need to think of the execution of a recursive program as a stack with a basic case and a general case:
For instance the factorial method:
Basic case: f(n) = 1, if n = 0.
General case: f(n) = n*f(n-1), otherwise.
Result would be:
f(n) = n*f(n-1)
f(n-1) = (n-1)*f(n-2)
...
f(2) = 2*f(1)
f(1) = 1*f(0)
f(0) = 1
Basically you need to go down until the basic case and then reconstruc the result via the partial results you are finding.
Recursive algorithms are very useful for some methods which otherwise would require lots of memory to store intermediates value.