I Need an explanation about the next recursion (I'm a beginner) - java

I know that lowkey it does 1 + 2 + 3 + 4 = 10, but I want to know how exactly it does that
public class Main {
public static int sum(int n) {
if(n == 0) return 0;
return sum(n - 1) + n;
}
public static void main(String[] args) {
System.out.println(sum(4));
}//main
}//class

public static int sum(int n) {
if(n == 0) return 0;
return sum(n - 1) + n;
}
When you call sum(4), the compiler does the following steps:
sum(4) = sum(3) + 4, sum(3) then calls sum(int n) and go to next step
sum(3) = sum(2) + 3, sum(2) then calls sum(int n) and go to next step
sum(2) = sum(1) + 2, sum(1) then calls sum(int n) and go to next step
sum(1) = sum(0) + 1, sum(0) then calls sum(int n) and go to next step
sum(0) = 0, return the value and bring it to previous step.
Then with backtracking, the compiler brings the value of sum(0) to the formula sum(0) + 1, so the value of sum(1) is 1. And so on, finally we get sum(4) is 10.

The key to understanding how this recursion work is the ability to see what is happening at each recursive step. Consider a call sum(4):
return
sum(3) + 4
sum(2) + 3
sum(1) + 2
sum(0) + 1
return 0 in next recursive call
It should be clear how a sum of 10 is obtained for sum(4), and may generalize to any other input.

Okay so lets understand it :
you call the method from main method passing the argument as 4.
It goes to method , the very first thing it checks is called as base condition in recursion . Here base condition is if n == 0 return 0.
We skipped the base condition since n is not yet zero . we go to return sum(n-1)+n that is sum(4-1)+4 . So addition will not happen , because you made the recursive call again to sum method by decrementing the n value to n-1 , in this case it is 3.
You again entered the method with n =3, check the base condition which is not valid since 3 != 0 , so we go to return sum (n-1)+3 , which is sum(3-1)+3
Next recursive call where n = 2 , base condition is not valid 2!=0 , so we return sum(n-1)+2that is sum(2-1)+2.
Next call with n = 1 , base condition is not valid , we go to return sum(n-1)+1 that is sum(1-1)+1.
Next recursive call with n = 0 , so now base condition is met , means it is time to stop the recursion and keep going back to from where we came to get the desired result. So this time we returned 0.
Lets go back to step 6 , with 0 we got and compute the addition part of sum(1-1)+1 . You got sum(1-1) => sum(0) = . So sum(1-1)+1 will be equal to 0+1=1
One more step back with 1 as value to step 5 , where we have sum(2-1)+2 = sum(1)+2 , sum(1) you know , which is 1 , so we will return 1+2=3 from this recursive call.
One step back with value as 3 , to step 4 , sum(3-1)+3 = sum (2)+3 = 3+3 =6 .
Going one step back with 6 as value to step 3 , sum(4-1)+4 = sum(3)+4 = 6+4 = 10 . And that is where we started from . You got the result as 10.

Recursion itself is very easy to understand.
From a mathematical point of view, it is just a simple function call, such as your code:
public static int sum(int n) {
if(n == 0) return 0;
return sum(n - 1) + n;
}
/*
sum(0) = 0
sum(1) = 1
sum(n) = n + sum(n-1)
*/
In fact, the concept of recursion has been introduced in high school. It is the "mathematical construction method" that is often used to prove sequence problems. The characteristics are obvious: the structure is simple and the proof is crude. As long as you build the framework, you can prove it in conclusion. So what is a recursive "simple structure" framework?
Initial conditions: sum(0) = 0
Recursive expression: sum(n) = sum(n-1) + n
And in fact about the sum() function, every calculation starts from sum(0), and it is natural. Even if you are asked to calculate sum(1000), all you need is paper, pen, and time, so recursion itself is not difficult.
So why recursion give people an incomprehensible impression? That's because "recursive realization" is difficult to understand, especially using computer language to realize recursion. Because the realization is the reverse, not to let you push from the initial conditions, but to push back to the initial conditions, and the initial conditions become the exit conditions.
In order to be able to reverse the calculation, the computer must use the stack to store the data generated during the entire recursion process, so writing recursion will encounter stack overflow problems. In order to achieve recursion, the human brain has to simulate the entire recursive process. Unfortunately, the human brain has limited storage, and two-parameter three-layer recursion can basically make you overflow.
Therefore, the most direct way is to use paper to record the stacks in your head. It is very mechanically painful and takes patience, but problems can often be found in the process.
Or, go back to the definition of recursion itself.
First write the architecture and then fill it in. Define the exit conditions and define the expression.
Second implement the code strictly according to the architecture. Recursive code is generally simple enough, so it is not easy to make mistakes in implementation. Once there is a problem with the program result, the first should not be to check the code, but to check your own definition.
Meeting Infinite loop? The initial conditions are wrong or missing; wrong result? There is a problem with recursion. Find out the problem, and then change the code according to the new architecture. Don't implement it without clearly defining the problem.
Of course, it really doesn't work. There is only one last resort: paper and pen.

Related

Recursion gives unexpected/wrong output?

So I was doing a recursion challenge on codingbat and came across the "bunny ears" problem where we have a number of bunnies and each bunny has two big floppy ears. We want to compute the total number of ears across all the bunnies recursively (without loops or multiplication).
The solution apparently is quite simple:
public int bunnyEars(int bunnies)
{
if(bunnies == 0)
return 0;
return 2+bunnyEars(bunnies-1);
}
But I am not able to understand. If we pass 2 in the bunnyEars(2) method the
recursive part bunnyEars(bunnies-1); should have 1 left in the bracket after subtraction and thus 2+(1); which should be equal to 3 and not 4.
But the output comes as 4. So how does recursion actually work in this code?
It is not 2+(1), it is 2+numberOfEarsOfBunnies(1) == 2+2.
I renamed the function a little to make it more obvious.
Or even more into detail:
numberOfEarsOfBunnies(2)==
2+numberOfEarsOfBunnies(1)==
2+(2+numberOfEarsOfBunnies(0))==
2+(2+0)==
2+2==
4
if we pass 2 in the bunnyEars(2) method the recursive part bunnyEars(bunnies-1); should have 1 left in the bracket after subtraction and thus 2+(1); should be equal to 3 and not 4.
It seems you're misreading the expression. The line of code in question says
return 2+bunnyEars(bunnies-1);
Now you call bunnyEars(2), so bunnies == 2; and then you reach this line of code.
return 2+bunnyEars(bunnies-1);
resolves to
return 2+bunnyEars(2-1);
or
return 2+bunnyEars(1);
So a second instance of the bunnyEars() function starts running, with bunnies == 1. It reaches that same line of code, and this time
return 2+bunnyEars(bunnies-1);
is
return 2+bunnyEars(1-1);
or
return 2+bunnyEars(0);
So a third instance of bunnyEars() gets running, with bunnies == 0; but this matches your base case, so you just return 0 ; this time we don't recurse. So back up a level we find that
return 2+bunnyEars(0);
is
return 2+0; // because bunnyEars(0) returned 0
so that instance returns 2. And that means
return 2+bunnyEars(1);
becomes
return 2+2; // because bunnyEars(1) returned 2
And of course 2+2 is 4, the correct answer.
It seems as though you applied the -1 to the return value of the recursive bunnyEars() call, but the code says to apply it to the parameter you're sending in, not to the return value.

Recursion confusion with multiple return

I'm still wrapping my mind around recursion, and I think I get basic ones like factorial. But I'd like further clarification when the return statement is a little more complex like on the following snippet:
/**
* #param n >= 0
* #return the nth Fibonacci number
*/
public static int fibonacci(int n) {
if (n == 0 || n == 1) {
return 1; // base cases
} else {
return fibonacci(n-1) + fibonacci(n-2); // recursive step
}
}
In the return statement, does the fibonacci(n-1) completely recur through, before going down the fibonacci(n-2) step (does that make sense)? If so, this seems very difficult to envision.
Yes, one invocation will recurse all the way down and return, before the other one starts executing.
The order of invocation in Java is well-defined: fibonacci(n-1) goes before fibonacci(n-2).
Edit: Since the question originally included [C++] tag, here is the C++ part of the story: one of the two invocations still has to complete before the other one starts to run, but which one, fibonacci(n-1) or fibonacci(n-2), is unspecified.
Since the function has no side effects, it does not matter which of the two invocations gets to run first. The only thing that is important for understanding of recursion is that both invocations must complete, and their results must be added together, before the invocation at the current level returns.
It isn't much more different than calling a different function than itself. It needs to finish before the calling function can do anything with the result.
finobacci(0); // ==> 1 (since n is zero, the base case is to return 1)
fibonacci(1); // ==> 1 (since n is one, the base case is to return 1)
Now lets try 2 which is not the base case:
fibonacci(2); // == (since it's not the base case)
fibonacci(1) + fibonacci(0); // == (both calls to fibonacci we already haver done above)
1 + 1 // ==> 2
So in reality what happens is that the call to fibonacci2 waits while each of the two recursive calls to finish, just like a function that does System.out.println would wait until it had printed the argument before continuing to the next line. Recursion isn't that special.
Trivia: This is the original series from Fibonacci himself. Modern mathematicians start the series with n as the base case result making the series 0, 1, 1, 2, ... rather than 1, 1, 2, 3, ....
it works in this way:
Fibonacci program:
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
Explanation:
In fibonacci sequence each item is the sum of the previous two. So, as per recursive algorithm.
So,
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(3) = fibonacci(2) + fibonacci(1)
fibonacci(4) = fibonacci(3) + fibonacci(2)
fibonacci(2) = fibonacci(1) + fibonacci(0)
Now you already know fibonacci(1)==1 and fibonacci(0) == 0. So, you can subsequently calculate the other values.
Now,
fibonacci(2) = 1+0 = 1
fibonacci(3) = 1+1 = 2
fibonacci(4) = 2+1 = 3
fibonacci(5) = 3+2 = 5
In multiple recursion the program calls itself with its first call until the base case is reached, in this case fibonacci(n-1); after that the recursion stops and return his value to continue calling the value to the second part of the recursion fibonacci(n-2).
If you don't visualize the multiple recursion in the program, this
fibonacci recursion tree may be helpful.

Reversing recursive java methods

I am reading a book called "Think Java: How to think like a Computer Scientist", and I recently covered recursive methods.
public static void countdown(int n)
{
if (n == 0) {
System.out.println("Blastoff!");
} else {
System.out.println(n);
countdown(n - 1);
}
}
This would be a normal recursive method used to count down to 0 and I understand what is happening, but if you make the recursive call before the System.out.println like this
public static void countdown(int n)
{
if (n == 0) {
System.out.println("Blastoff!");
} else {
countdown(n - 1);
System.out.println(n);
}
}
it counts the opposite way, so If I gave the argument 3 for both of these conditional statements the 1st one goes "3, 2, 1, Blastoff!" but the 2nd 1 goes "Blastoff, 1 ,2 ,3".... I don't understand how this works, can someone try to explain what is happening in this code that makes it count in the opposite way?
I'll try to visualize it for you.
First method
countdown(3) (first call)
"3" (sysout)
countdown(3-1) (second call)
"2" (sysout)
countdown(2-1) (third call)
"1" (sysout)
countdown(1-1) (fourth call)
"Blastoff!" (n == 0)
Second method
countdown(3) (first call)
countdown(3-1) (second call)
countdown(2-1) (third call)
countdown(1-1) (fourth call)
"Blastoff!" (n == 0. going back up call stack)
"1" (sysout)
"2" (sysout)
"3" (sysout)
Think of it this way... In the first case you will always print before going down the next function, so...
countdown(3)
System.out.println(3)
countdown(2)
System.out.println(2)
countdown(1)
System.out.println(1)
countdown(0)
System.out.println("Blastoff")
Result: 3 2 1 Blastoff
In the second case, because you print it first, your run will go all the way down the recursion until the base case to start printing...
countdown(3)
countdown(2)
countdown(1)
countdown(0)
System.out.println("Blastoff")
System.out.println(1)
System.out.println(2)
System.out.println(1)
Result: 1 2 3 Blastoff
Recursion is tough! I hope I helped :)
It doesn't count "the opposite way", it's just that it "unravels" in an order you are perhaps not expecting. Try writing out what you expect to happen and I'll be happy to help resolve the misconception.
The issue is that the print line is going to wait until your function call(s) have finished. Therefore it will call the function 3 times in a row before it gets to the first print line
The whole point of recursion is that every step gets its own "stack frame" with its own local variables, that it remembers.
So even if you change n inside of one iteration, the function that called this iteration will still retain its own value of n. When the time comes to print this n it will still be the original value (one bigger than the one in the following iteration).

Understanding Java recursion using Eclipse's debugger

I am going through some simple recursion exercises in Java in order to understand the concept (which I struggle with). For all my study up to this point, I have relied heavily on Eclipse's debugger in order to understand exactly what my code is doing. However, when it comes to recursion, I find this not to be the case, because it is difficult to track exactly what is happening.
Considering the following code, a method that returns the nth Fibonacci number:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
When using the debugger for this code, it's pretty difficult to track exactly what is happening and where/when. With only one variable, it changes every step, and, with a small n value, such as 7, it is already becoming difficult to track, due to the fact that there are so many steps that are executed before 13 is eventually reached.
I would like to know:
How can I debug my recursion code (in general) in a better way, in order to better understand recursion?
Am I focussing too much on debugging for this sort of thing, considering the concept return fibonacci(n - 1) + fibonacci(n - 2) is simple to understand?
How can I debug my recursion code?
First, make sure you have switched to the Debug perspective and you're seeing the correct windows (Variables, Expressions, Debug and your source code) e.g. like this:
Next, note that in Debug you can see how often the method is currently called. This list will grow and shrink depending on how many methods were called and have not returned yet.
You can click on one of the methods to change the scope. See how the contents of Variables changes when you change the scope.
Finally, to check arbitrary things, enter expressions in the Expressions window. This is almost like live coding. You can inspect virtually anything.
Am I focussing too much on debugging?
No. Learn doing it right and it will save you much time later.
Adding a System.out.println() needs to recompile and you need to reproduce the situation which is not always that simple.
You can debug it using a simple System.out.prinln() in each instruction where you print n value and its fibonnacci value.
Here's an example code:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
System.out.println("your value is: " +n+ " and its Fibonacci value is: "+n);
return n;
} else {
System.out.println("your value is: " +n+ " and its Fibonacci value is: "+fibonacci(n - 1) + fibonacci(n - 2));
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
You can test the DEMO here.
"Inline" code makes it more difficult to use the Eclipse debugger because it has a strong focus on showing local variables which are not present. You can make this easier to step through by making things more verbose and saving to variables. This way you can more easily see what is happening and what results are. For example, modifying your code as follows will make it easier to use the debugger on:
public int fibonacci(int n) {
if (n == 0 || n == 1) {
return n;
} else {
int nMinus1 = fibonacci(n - 1);
int nMinus2 = fibonacci(n - 2);
int retValue = nMinus1 + nMinus2;
return retValue;
}
}
DISCLAIMER: I have not attempted to compile this code.
It took me a while to grasp recursion and, for one reason or another, I never found the debuggers useful. I'll try to explain you how I do and it doesn't involve the debugger (disclaimer: this is a personal method and it might by incorrect or not general).
In recursive code you always have at least a termination block and a
recursion block. Isolate mentally these 2 sections.
return n; -> termination block
return fibonacci(n - 1) + fibonacci(n - 2); -> recursion block
The recursion block express the abstract rule(s) of recursion. Instead of having those values in variables Fn1 and Fn2, you obtain these values using the same function. Think about a brick wall: your recursive function creates the wall adding a brick to an existing wall. Inside the recursion block, at a certain step, you don't mind who and how the existing wall has been created, you simply add to it a new brick. It happens then that the wall has been created by the same function, one brick at the time.
At the termination block the code is called with some values. What should happen at the end of the process to that value? Speaking about Fibonacci, at the end of the process (n = 1 or n = 0) I have to again add these number to the total. This is done by the recursive block. In other words the termination block gives the concrete values (and not a process on how to obtain them) to the recursion block.
When I have to troubleshoot I print the values at every step, and this is the best solution I've found for me. Then I check that they are what they are supposed to be. For your Fibonacci, I would like to see an output like
Code:
public static int fibonacci( int n ) {
System.out.println( "\nInput value: " + n );
if( n == 0 || n == 1 ) {
System.out.println( "Terminating block value: " + n );
return n;
}
else {
System.out.println( "Recursion block value: fibonacci(" + (n - 1) + ") + fibonacci(" + (n - 2) + ")" );
int result = fibonacci( n - 1 ) + fibonacci( n - 2 );
System.out.println( "Recursion block return value: " + result );
return result;
}
}
Output:
Input value: 4
Recursion block value: fibonacci(3) + fibonacci(2)
Input value: 3
Recursion block value: fibonacci(2) + fibonacci(1)
Input value: 2
Recursion block value: fibonacci(1) + fibonacci(0)
Input value: 1
Terminating block value: 1
Input value: 0
Terminating block value: 0
Recursion block return value: 1
Input value: 1
Terminating block value: 1
Recursion block return value: 2
Input value: 2
Recursion block value: fibonacci(1) + fibonacci(0)
Input value: 1
Terminating block value: 1
Input value: 0
Terminating block value: 0
Recursion block return value: 1
Recursion block return value: 3
You can also find useful to read about Induction, which is strictly related to recursion.

Java Recursion - Did I do this right? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
My job is to write a recursive version to this method. From what I understand Recursion is starting with a base call (if something then return) followed by an else which unwinds back to the original base. Like starting with a deck, adding on to the deck then removing cards from the deck until you are back to the original deck.
With that in mind here it is.
public static long fact(int n)
{
long result = 1;
while(n > 0)
{
result = result * n;
n = n - 1;
}
return result;
}
//my recursive version:
public static void recFact(int n)
{
if(n==0)
{
return n; // ir 0 it really doesn't matter right?
}
else
{
return recFact(n-1);
}
}
This is just an example test problem for an exam I have coming up, just want to make sure I have a handle on recursion. Did I do this right? If not what am I missing? please no answers in questions, just tell me what I did wrong and maybe some advice on better ways to understand it.
Thanks.
No, this recursive solution is not correct.
For every positive n, you're just return rectFact(n-1), which will recourse until you reach 0, at which point it will return. In other words, your function will always return 0. You're missing the part where you multiply the current n with rectFact(n-1). Additionally, note that 0! is 1, not 0:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
else
{
return n * recFact(n-1);
}
}
And finally, since the if clause returns, the else is somewhat redundant. This doesn't affect the method's correctness, of course, but IMHO the code looks cleaner without it:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
return n * recFact(n-1);
}
Your recursive version does no multiplication, and it will return zero for any input. So no, you didn't do it right.
But, the recursive version DOES recurse, so you have that going for you! To understand what's going wrong, walk through a very simple case.
Client calls recFact(3)
This will return to client recFact(2)
Which will return to above recFact(1)
Which will return to above recFact(0)
Which will return to above 0.
There are two major things going wrong:
Your base case is wrong (zero is too low)
You're not doing any multiplication
Good attitude about not wanting the solution handed to you! Hopefully these pointers wil help you figure it out.
EDIT: Apparently I misunderstood your grammar and you did want the solution.
Any recursive function needs three things:
The terminating condition: This tells the function when to stop calling itself. This is very important to avoid infinite recursion and avoid stack overflow exceptions.
The actual processing: You need to run the actual processing within each function. In your non recursive case, this was result = result * n. This is missing from your recursive version!
A collector/agggregator variable: You need some way to store the partial result of the recursive calls below you. So you need some way to return the result of recFact so that you can include it in processing higher up in the call chain. Note that you say return recFact(n - 1) but in the definition recFact returns void. That should probably be an int.
Based from your example you are missing the return type of your recFact which is int
Also recFact will always return 0 because you are not multiplying n each time to the recursion call of the method.
There are two ways to write recursive routines. One is the "standard" way that we all are taught. This is one entry point that must first check to see if the recursive chain is at an end (the escape clause). If so, it returns the "end of chain" value and ends the recursion. If not at the end, it performs whatever calculation it needs to get a partial value according to the level and then calls itself passing a value the next increment closer to the end of the chain.
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int val ){
if( val < 2 ){
return 1;
}
else{
return recFact( val - 1 ) * val; // recursive call
}
}
//Output: "Fact(15) = 2004310016"
In regular recursion, a partial answer is maintained at each level which is used to supplement the answer from the next level. In the code above, the partial answer is val. When first called, this value is 15. It takes this value and multiplies it by the answer from Fact(14) to supply the complete answer to Fact(15). Fact(14) got its answer by multiplying 14 by the answer it got from Fact(13) and so on.
There is another type of recursion called tail recursion. This differs in that partial answers are passed to the next level instead of maintained at each level. This sounds complicated but in actuality, make the recursion process much simpler. Another difference is that there are two routines, one is non recursive and sets up the recursive routine. This is to maintain the standard API to users who only want to see (and should only have to see)
answer = routine( parameter );
The non-recursive routines provides this. It is also a convenient place to put one-time code such as error checking. Notice in the standard routine above, if the user passed in -15 instead of 15, the routine could bomb out. That means that in production code, such a test must be made. But this test will be performed every time the routine is entered which means the test will be made needlessly for all but the very first time. Also, as this must return an integer value, it cannot handle an initial value greater than 19 as that will result in a value that will overflow the 32-bit integer container.
public static final int MaxFactorialSeq = 20;
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int value ){
if( value < 0 || value > MaxFactorialSeq ){
throw new IllegalArgumentException(
"Factorial sequence value " + value + " is out of range." );
}
return recFact( value, 1 ); // initial invocation
}
private int recFact( int val, int acc ){
if( val < 2 ){
return acc;
}
else{
return recFact( val - 1, acc * val ); // recursive call
}
}
//Output: "Fact(15) = 2004310016"
Notice the public entry point contains range checking code. This is executed only once and the recursive routine does not have to make this check. It then calls the recursive version with an initial "seed" of 1.
The recursive routine, as before, checks to see if it is at the end of the chain. If so, it returns, not 1 as before, but the accumulator which at this point has the complete answer. The call chain then just rewinds back to the initial entry point in the non-recursive routine. There are no further calculations to be made as the answer is calculated on the way down rather than on the way up.
If you walk though it, the answer with standard recursion was reached by the sequence 15*14*13*...*2*1. With tail recursion, the answer was reached by the sequence 1*15*14*...*3*2. The final answer is, of course, the same. However, in my test with an initial value of 15, the standard recursion method took an average of 0.044 msecs and the tail recursion method took an average of 0.030 msecs. However, almost all that time difference is accounted for by the fact that I have the bounds checking in my standard recursion routine. Without it, the timing is much closer (0.036 to 0.030) but, of course, then you don't have error checking.
Not all recursive routines can use tail recursion. But then, not all recursive routines should be. It is a truism that any recursive function can be written using a loop. And generally should be. But a Factorial function like the ones above can never exceed 19 levels so they can be added to the lucky few.
The problem with recursion is that to understand recursion you must first understand recursion.
A recursive function is a function which calls itself, or calls a function which ultimately calls the first function again.
You have the recursion part right, since your function calls itself, and you have an "escape" clause so you don't get infinite recursion (a reason for the function not to call itself).
What you are lacking from your example though is the actual operation you are performing.
Also, instead of passing a counter, you need to pass your counter and the value you are multiplying, and then you need to return said multiplied value.
public static long recFact(int n, long val)
{
if(n==1)
{
return val;
}
else
{
return recFact(n-1, val) * n;
}
}

Categories

Resources