I'm trying to understand how recursion works. I have two codes that have different outputs due to the placement of the recursive call. I understand that it's SUPPOSED to have different outputs, but I don't understand WHY the output is what it is.
Code 1 (recursive call placed AFTER print):
public class Test {
public static void main(String[] args) {
xMethod(5);
}
public static void xMethod(int n) {
if (n > 0) {
System.out.print(n + " ");
xMethod(n - 1);
}
}
}
The above output is 5 4 3 2 1. I understand why I get this output. It's because first, 5 is printed, then 5 is deducted by 1 and 4 is printed, and so on.
What is I don't understand is the output of the following code, when the recursive call is place before the print.
Code 2 (recursive call placed before print):
public class Test {
public static void main(String[] args) {
xMethod(5);
}
public static void xMethod(int n) {
if (n > 0) {
xMethod(n - 1);
System.out.print(n + " ");
}
}
}
The above output is 1 2 3 4 5. I can't figure out why I get this output. I would imagine the output to be 4 3 2 1, as the 5 is deducted, then printed as 4, and so on. But this obviously is not the case.
Can someone help me understand what is going on in the recursive process?
In first case printing is done and then call happens.
In second case calls happens in this way :
x(5) -> x(4) -> x(3) -> x(2) -> x(1) -> print(1) ->print(2) ->print(3) ->print(4) -> print(5)
Printing starts from the end call.
x(5)
|
x(4) print(5)
| |
x(3) print(4)
| |
x(2) print(3)
| |
x(1) print(2)
| |
print(1)
In case of first
print(5)
x(5)
|
print(4)
x(4)
|
print(3)
x(3)
|
print(2)
x(2)
|
print(1)
x(1)
In the first script,
public static void xMethod(int n) {
if (n > 0) {
System.out.print(n + " ");
xMethod(n - 1);
}
}
The output is printed before the step into the recursive call.
In the second script,
public static void xMethod(int n) {
if (n > 0) {
xMethod(n - 1);
System.out.print(n + " ");
}
}
The function keeps stepping "into" the recursion i.e. once xMethod(n-1) is called, the line below it is not executed i.e. the print statement. And this keeps happening until the last recursive call has been executed i.e. when x == 1, then the call goes backward and starts all the print statements beginning with the print statement for x == 1, then the print statement for x == 2 e.t.c. until the last print statement for the first call.
I have listed a stack trace of your second snippet's execution flow (Wish I could have aligned the table and 4 columns better)
If you step through your program when debugging it, you will obtain to a similar stack trace that tells you the value of the variables as you step through the program's execution flow, tabulated similar to the info listed below:
Stack trace| Value of Variable n | Statement executed | Output
main
xmethod(5) 5 xmethod(4)
xmethod(4) 4 xmethod(3)
xmethod(3) 3 xmethod(2)
xmethod(2) 2 xmethod(1)
xmethod(1) 1 xmethod(0)
xmethod(0) 0
xmethod(1) 1 System.out.print(1 + " ") 1
xmethod(2) 2 System.out.print(2 + " ") 1 2
xmethod(3) 3 System.out.print(3 + " ") 1 2 3
xmethod(4) 4 System.out.print(4 + " ") 1 2 3 4
xmethod(5) 5 System.out.print(5 + " ") 1 2 3 4 5
You should go through this tutorial(http://www.vogella.com/articles/EclipseDebugging/article.html) to get the hang of debugging. Debugging a program will help you to get a head-start to resolve queries like this one, yourself.
In the second code the line:
System.out.print(n + " "); will not be executed unless all the recursive calls get completed.
The recursive function is calling itself before executing the print line.
Related
In this program, if the user enters the number 3, the o/p will be 3 2 1 1 2 3 , I understood how 3 2 1 came, but I didn't understand how 1 2 3 came at the end.
class GFG{
static void printFun(int test)
{
if (test < 1)
return;
else
{
System.out.printf("%d ",test);
printFun(test-1); // statement 2
System.out.printf("%d ",test);
return;
}
}
public static void main(String[] args)
{
int test = 3;
printFun(test);
}
}
One way to trace through recursive functions is by expanding every recursive call, like a math expression.
First we start with
printFun(3)
That expands to:
print(3) // I have shortened System.out.printf here to just "print" to remove the noise
printFun(2)
print(3)
We still have a recursive call (printFun(2)), so let's expand that.
print(3)
print(2)
printFun(1)
print(2)
print(3)
Continue expanding:
print(3)
print(2)
print(1)
printFun(0)
print(1)
print(2)
print(3)
And one last time (since printFun(0) doesn't do anything, we just remove it):
print(3)
print(2)
print(1)
print(1)
print(2)
print(3)
Oh look! That will produce the output 3 2 1 1 2 3!
Ok - nature of recursions. Recursions put their calls on stacks which is built bottom-up. Whenever a member is recalled from the stack it is to be taken from the top till we reach the bottom again. Lets go through it line-per-line:
function is called 1st time with 3
function writes: 3 and calls itself with 2 - function halts (right after statement2) and waits for execution
function writes: 2 and calls itself with 1 - function halts and waits for execution
function writes: 1 and calls itself with 0 - call returns immediately because of value 0. Time to reduce the caller-stack and continue halted functions.
last function halt is reactivated (it was 1) and writes: 1 - then function returns
last function halt is reactivated (it was 2) and writes: 2 - then function returns
last function halt is reactivated (it was 3) and writes: 3 - then function returns
program stops.
Therefore you get the line of numbers you wrote.
The recursive invocation printFun(test-1) make the method goes on to invoke it in this way :
printFun(3); // original
printFun(2);
printFun(1);
printFun(0);
Arriving at this time it doesn't perform any other recursive call because of the condition encountered for printFun(0).
The current call that is the last recursive call (printFun(0)) goes on with return. Then the execution goes up to the caller of printFun(0) that is printFun(1) that executes the second System.out.printf("%d ",test); statement and it returns.
Then same logic : The execution goes up to the method that invoked that, that is printFun(2).
And that goes on to go up until the initial one invocation.
You can see calls in this way :
printFun(3)
printFun(2)
printFun(1)
printFun(0)
-- No more recursive call, execution goes on where we are
printFun(0)
printFun(1)
printFun(2)
printFun(3)
I added some print commands to help you understand this.
class GFG{
static int count = 1;
static String combined = "";
static void printFun(int test){
System.out.println("No of times Function printFun has been called : " + count);
count = count + 1;
if (test < 1)
return;
else{
System.out.println("Adding " + test + " to combined string");
combined = combined + test;
printFun(test-1); // statement 2
System.out.println("Returning to the previous call of printFun");
combined = combined + test;
System.out.println("Adding " + test + " to combined string");
return;
}
}
public static void main(String[] args){
int test = 3;
printFun(test);
System.out.println(combined);
}
}
I'm printing out the combined string at the end, the print statements should indicate how the function gets recursively called.
Function calls are maintained by stack. All local variables of the function corresponds to the function call instance. Each function call instance is maintained in Stack.
Statement above Recursive call is a PUSH operation and after recursive call is POP operation.
Hence its
(Statement before recursive call)
print(3) PUSH(3), print (2) PUSH(2), print(1) PUSH(1)
followed by
(Statement after recursive call).
POP(1) print(1), POP(2) print(2) , POP(3) print(3)
Hence output is 3 2 1 1 2 3
Here is the reference Program Code :-
The Program must also give -1 as the output. However I cant find the reason. Please Explain, and tell me the Stack which would be made.
class test
{
public static void main(String args[])
{
test ob=new test();
ob.numbers(5);
}
public void numbers(int n)
{
if(n>0)
{
System.out.print(n+" ");
numbers(n-2);
System.out.print(n+" ");
}
}
}
Call Stack goes this way:
numbers(n) // n = 5
{
n>0 ? YES
Print n -- Print 5
call numbers(n-2) //n-2 = 3
numbers(n) // n=3
{
n>0 ? YES
Print n -- Print 3
call numbers(n-2) //n-2 = 1
numbers(n) // n=1
{
n>0 ? YES
Print n -- Print 1
call numbers(n-2) //n-2 = -1
numbers(n) // n=-1
{
n>0 ? NO As Per the code, does nothing
}
Print n -- Print 1
}
Print n -- Print 3
}
Print n -- Print 5
}
Hope this helps.
I have a simple java program that takes a number and executes a function based on that number.
public class Palidrome {
public static void main (String[] args) {
int N = 3;
System.out.println(palidrome(N));
}
public static String palidrome(int i) {
if (i == 0) return "S";
if (i == 1) return "T";
return palidrome(i-2)
+ palidrome(i-1)
+ palidrome(i-2);
}
}
So for this example N = 3, and the output is "TSTST". If N is changed to 5, the output is "TSTSTSTSTSTSTSTSTSTST" etc.
I'm struggling to figure out why this is the case. If N = 5, palidrome(i-1) and palidrome(i-2) will never reach (i == 0) or (i == 1) so nothing should be returned theoretically?
Thanks in advance!
This can be understood by drawing the recursion tree.
palindrome(5)
/ | \
palindrome(3) palindrome(4) palindrome(3)
/ | \ ............................
/ | \
palindrome(1) palindrome(2) palindrome(1)
/ | \
/ | \
palindrome(0) palindrome(1) palindrome(0)
So palindrome(5) will ultimately reach palindrome(0) and palindrome(1) calls.
NOTE: The recursion ends at palindrome(0) and palindrome(1) calls.
Let's run through what happens line by line for N = 5.
palindrome(5) is called
--> i is not 0 or 1
--> return the results of palindrome(3) + palindrome(4) + palindrome(3)
We need the results of palindrome(3) to build our result for palindrome(5). So palindrome(3) is called.
--> i is not 0 or 1
--> return the results of palindrome(1) + palindrome(2) + palindrome(1)
We need the results of palindrome(1) to build our result for palindrome(3). So palindrome(1) is called.
--> i = 1, so "T" is returned
We need the results of palindrome(2) to build our result for palindrome(3). So palindrome(2) is called.
--> i is not 0 or 1
--> return the results of palindrome(0) + palindrome(1) + palindrome(0)
I'll glaze over the recursion here, but we get "STS" for the results for palindrome(2).
This means we get palindrome(1) + palindrome(2) + palindrome(1) = "TSTST" for palindrome(3).
This result is returned to our original palindrome(5) call.
Hopefully that helps illustrate the recursion for you.
Each successive recursive call for palidrome should bring you closer to the base-case which is here:
if (i == 0) return "S";
if (i == 1) return "T";
so theoritcally saying
palidrome(i-1) and palidrome(i-2) will never reach (i == 0) or (i ==
1)
is wrong as those statements will be eventually reached but after the i changes to satisfy the condition.
How would var i change you are probably wondering! well through this statement:
return palidrome(i-2)
+ palidrome(i-1)
+ palidrome(i-2);
Here you are calling palidrome recursively but (i is decreased), this will eventually lead you to the base-case.
if your function never hit the base-case then you'll have an infinite recursion and this is not the case over here.
To simplify things lets take a look at this Example:
assume that you have a generous neighbor that will give you one apple if you visit him once, also another one if you visit him twice then he'll start giving you as mush as he gave you that last 2 times (that's actually a fibonacci sequence) so the general-case here is:
numberOfApplesThatYouGet= numberOfApplesThatYou'veGotIn(currentVisitNumber-1(Which is Last Visit))+numberOfApplesThatYou'veGotIn(currentVisitNumber-2)
and lets assume that
currentVisitNumber = n and numberOfApplesThatYouGet = a method called fib
so general rule would be -->
fib(n)=fib(n-1)+fib(n-2)
But we still need a base-case to terminate an infinite recursion and here the base-case is your first visit condition which is
if(n==0) return 0;//if you didn't visit him you'll get nothing
if(n==1) return 1;//if you did you'll get an apple
so the Method will look like this:
public int fib(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
lets assume that you bare him three visits, how many apples would you get?
fib(3)->fib(2)+fib(1)
fib(2)->fib(1)+fib(0)->1+0->1
fib(1)->1
1+1=2
#done
Also take a look at this to form a better understanding of recursion.
When I run this piece of code for n=5 the output I get is "5 3 1 1 3 5"
I get the 5 3 1 part but after that n=-1 but when I run the code with a debugger it when n=-1 it goes to the line after numbers(n-2);i.e System.out.prt(n+ ""); even though that statement is contained in the if block.
Why does this happen?
public void numbers(int n)
{
if(n>0)
{
System.out.print(n+" ");
numbers(n-2);
System.out.print(n+" ");
}
}
TLDR : when n=-1 System.out.prt(n+ "");even though it is within the if block which only runs when n>0.
Any help would be much appreciated. Thanks in advance!
Here is what happens behind the scenes, for n == 5:
numbers(5);
if(5 > 0)--> true :
System.out.print(5 + " "); // (1)
numbers(3);
| if(3 > 0)--> true :
| System.out.print(3 + " "); // (2)
| numbers(1);
| | if(1 > 0)--> true :
| | System.out.print(1 + " "); // (3)
| | numbers(-1);
| | System.out.print(1 + " "); // (4)
| System.out.print(3 + " "); // (5)
System.out.print(5 + " "); // (6)
Notice how each number is supposed to be printed twice:
System.out.print(n + " "); // print once
numbers(n-2);
System.out.print(n + " "); // print twice
Remove the final System.out.print(n+" ");
After the recursive numbers call it comes back with the original value for n and prints this again.
It bubbles back from the deepest level where it prints 1 two times up to the call with number 3, which is printed again, and also 5 is printed again.
If you want it to update the value after it is printed the first time you will have to update the variable n by performing n-=2 instead of n-2
5 first system.out then number(5-2)
|
----> 3 first system.out then number(5-2)
|
----->1 first system.out then number(5-2)
(smaller than 0) , returning
|
1 second system.out
|
3<---- second system.out
|
5<--------- second system.out
after n=-1, the recursive call will end and return back to the caller method to continue. first commands it found is print.
If you try to debug with the debugger, you will see how rational it is.
Java maintain method call into stack and as first 5,3,1 gets printed after which method call resume execution for remaining calls and prints 1,3,5 from stack(last call in stack get's picked up first).
Follow the recursion stack.
stack representation with and output flow:
------------------------->
5 3 1
num(5)--> num(3) --> num(1) --> num(-1) --> void
5 3 1
<-------------------------
Now since numbers(-1) does not satisfy the if condition, the program control comes out of the if block, and returns void.
Start popping out the stack now (recursion):
5 3 1 1 3 5. That's what the output you get, and is expected.
In the following function why After showing Hello(6,5,....1),then space shows increment in counter?
private void myMethod(int counter)
{
if (counter == 0)
{
System.out.println("");
}
else
{
System.out.println("Hello" + counter);
myMethod(--counter);
System.out.println("" + counter);
}
}
Program Output when 6 is passed to method:
Hello6
Hello5
Hello4
Hello3
Hello2
Hello1
0
1
2
3
4
5
The second print is first called if the recursion is fully done, this means it counts backwards, since the last called method finishes first.
If that's what you mean.
(not actually code but used for a diagram)
When using myMethod(3):
mM(3)->|prints: "Hello3"
|mM(2)-------------->|prints: "Hello2"
|prints:.... |mM(1)-------------->|prints: "Hello1"
|prints.... |mM(0)----------->|prints: ""
|prints....
because each else has three statements, and they do them in order from top to bottom, the first print statement is executed first, and then the recursion happens next, which temporarily skips the the second print until the base statement 0 is reached, and then it goes backwards and does the second print for each else. (if this is what you're asking)