I am a beginner in JAVA, and I am having some difficulties tracking recursion and understaning it fully and so here I have the code for a program that if we write 3, it will output:
1
12
123
12
1
Or if we write 5, it will output
1
12
123
1234
12345
1234
123
12
1
public class Aufgabe3 {
private static void printSequenz(int n) {
if(n<1) {
return;
}
printLoToHi(n-1);
printMany(n);
printHiToLo(n-1);
}
private static void printHiToLo(int n){
if(n<1){
return;
}
printMany(n);
printHiToLo(n-1);
}
private static void printLoToHi(int n){
if(n<1){
return;
}
printLoToHi(n-1);
printMany(n);
}
private static void printMany(int n){
for(int i=1;i<=n;i++){
System.out.print(i);
}
System.out.println();
}
public static void main(String[] args) {
printSequenz(5);
}
}
Now here is what I don't understand. For example at the method printHiToLo it calls the method printMany(n), and then it calls itself for n-1, and this repeats until n is greater than 0. But I don't understand how the method printLoToHi works? How does it ever reach the printMany method? If it just calls itself until n is greater than 0. This is really confusing to me... Thanks to anyone that helps me out :)
private static void printLoToHi(int n){
if(n<1){ // This is the base case that terminates the recursion.
return; // You'll always have one - sometimes more.
}
printLoToHi(n-1); // This is where the recursion takes place.
printMany(n); // But when n < 1 it returns to here and continues on.
}
So you see it does indeed get called; only after the base case (n < 1) is reached.
An easy example would be if you called it with printLoToHi(1)...
It will pass the if condition.
It calls itself with n - 1 (0) as an argument.
This time it fails the condition and returns.
n == 1 in our original method.
printMany(1) is called.
Look, your functions are executed line by line. So in printLoToHi recursive call is executed and then printMany is called.
For example how works printLoToHi(3):
It checks if 3 less than 1. Then calls printLoToHi(2).
It checks if 2 is less than 1. Then calls printLoToHi(1).
It checks if 1 is less than 1. Then calls printLoToHi(0).
It checks if 0 is less than 1. It is, so it returns.
Then printMany(1) is called.
Then printMany(2) is called.
Then printMany(3) is called.
You can consider a recursive call as a single function which does something and don't think how it works. You can assume it works and write other part of function. If that part is correct - the recursion is correct.
Related
Doing a very simple program to test out recursion. The program prints something until the number is not greater than 0.
public class TestIt {
public static void print(int f){
while(f>0){
System.out.println("Not today");
f--;
print(f);
}
}
}
the code above is called from the main program like this.
public static void main(String[] args) {
TestIt.print(2);
}
Maybe I'm finally losing my mind, but the amount of times the program prints is exceeding what I expected. If I send 3 to the method then the program prints 7 times. Any ideas as to why?
Because you did wrong
while(f>0){
System.out.println("Not today");
f--;
print(f);
}
you are calling the method print f in the loop times
and as it is recursive it will be called f-1 times recursivelly
so it will b f fatorial times
remove the while loop and will work as you want
This is because everytime the call comes off the stack, f is still what it was originally, and then it continues with the while loop. So for 2:
while(f>0){
System.out.println("Not today");
f--;
print(f);
}
First run, subtracts from 2, results in one. (Print count = 1) Resursive call:
Subtracts again, 0, recursive call: (Print count 2)
While loop is never entered. returns:
0, while loop is not executed, reuturns:
While loop is run again, recursive call: (print count = 3)
Passes zero, while loop not entered, return
While loop terminated, exit method
For 2 it prints three times, but this grows for every number passed in. To fix this do:
if(f>0){
System.out.println("Not today");
f--;
print(f);
}
Remember recursion usually is to avoid loops, so if you find yourself using both, this is usually a red flag
I'm learning recursion now, and I thought I quite understood how recursion works, and then I saw this code, and my head is about to explode.
I know this simple recursion works like
public void recursivePrint(int number){
if(number == 0{
return;
}
System.out.println(number + " ");
recursivePrint(number - 1);
}
If the parameter "number"'s value is 2.
public void recursivePrint(2){
if(number == 0{
return;
}
System.out.print(2 + " ");
recursivePrint(2 - 1);
}
public void recursivePrint(1){
if(number == 0{
return;
}
System.out.print(1 + " ");
recursivePrint(1 - 1);
}
and then stops because it meets its base case.
What about this print all permutations of a string function?
private void permute(String str, int l, int r)
{
if (l == r)
System.out.println(str);
else
{
for (int i = l; i <= r; i++)
{
str = swap(str,l,i);
permute(str, l+1, r);
str = swap(str,l,i);
}
}
}
There is a recursive call inside a for loop. If the input value is "ab", how does this recursion function work? Can you explain as I wrote above?
I got this code form geeksforgeeks, and there's a video for this, but I can't understand this since I don't know how loop works in recursion.
Using permute function you are generating strings where lth char is being replaced by one of the char following it. With the for loop inside it, you are touching onto each of those following characters one at a time.
With several call to permute, you are able to advance till the end position of the string, and that end is checked by if (l == r)
Take the case of abc.
abc
/ | \
Level 1 a(bc) b(ac) c(ba) (Here three new call to permute are made out of permute with l=1)
Goes on...
FYI, permutation isn't that simple to understand if you are new to recursion or programming. For easy understanding use pen-paper.
Recursion occurs when a method calls itself. Such a method is called recursive. A recursive method may be more concise than an equivalent non-recursive approach. However, for deep recursion, sometimes an iterative solution can consume less of a thread's finite stack space.
What is recursion:
In general, recursion is when a function invokes itself, either directly or indirectly. For example:
// This method calls itself "infinitely"
public void useless() {
useless(); // method calls itself (directly)
}
Conditions for applying recursion to a problem:
There are two preconditions for using recursive functions to solving a specific problem:
There must be a base condition for the problem, which will be the endpoint for the recursion. When a
recursive function reaches the base condition, it makes no further (deeper) recursive calls.
Each level of recursion should be attempting a smaller problem. The recursive function thus divides the problem into smaller and smaller parts. Assuming that the problem is finite, this will ensure that the recursion terminates.
In Java there is a third precondition: it should not be necessary to recurse too deeply to solve the problem;
The following function calculates factorials using recursion. Notice how the method factorial calls itself within the function. Each time it calls itself, it reduces the parameter n by 1. When n reaches 1 (the base condition) the function will recurse no deeper.
public int factorial(int n) {
if (n <= 1) { // the base condition
return 1;
} else {
return n * factorial(n - 1);
}
}
I have this odd issue I can't explain to myself, when using short if inside of return. This code (see below) should return the value 55 but instead it just returns the argument 10 which I passed to it by value.
I already debugged the function and the recursion works as intended but it never adds the + 1 to the return value.
public static int add(int i) {
return i == 0 ? 0 : add(i - 1) + 1;
}
public static void main(String[] args) {
System.out.println(add(10)); // returns 10
}
How come this doesn't work?
Your code does what you're telling it to. At each recursion step it reduces one from the counter and adds 1 to the result - since it's counting i times, it'll return i.
What you're trying to do is sum the numbers from 0 to i. In order to do this you need to add i and not 1 to the sum each time.
public static int add(int i) {
return i == 0 ? 0 : add(i - 1) + i; // <- like this
}
Since this is likely an exercise, consider implementing factorial recursively to make sure you understand the concept (that is, a function that takes n and returns n * (n-1) * (n-2) ... and so on.
I am trying to understand the working of return statement in JAVA.
My doubt is if inside a method with a Non void return type, I have a decision block which also has a return statement of its own, Still I have to return some value .
For understanding here is a sample code I have written :-
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count1;
}
return count2 ;
}
In the mentioned code I just want to return the no. of bunnies which I am being able to do from inside the bunnyEars method count1. But still JAVA wont allow to have a non-void method without a return type which is totally understood and I have to add count2 return also. Now I am suspecting that I am having a conceptual understanding failure here. Kindly let me know if I am missing something? Kindly let me know If I am missing some more info here.
[Edited] Full code:
public class Test5 {
//public int ears=1;
public int count=0;
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count;
}
return count ;
}
public static void main(String args[]){
Test5 test5= new Test5();
System.out.println(test5.bunnyEars(90));
}
}
Yes you need to return count2 which should be zero. Which means if there are no bunnies then there are no ears. So which returning you should be returning some value irrespective of the conditional block.
So in this case
return count1;
represents the number of ears if the bunnies are represent, while
return count2;
represents the number of ears when there are no bunnies, which should be 0.
I hope that gives you some clarification
I think your conceptual misunderstanding lies with understanding the flow of the program.
Supposed you were to use this method by calling:
bunnyEars(2)
Then, once you enter the method, the first thing the program does is check if 3 >= 1. Since this is true, you proceed into the code inside the {..} (called a 'block'). Inside this block, you increment count by 2. I am assuming count is defined elsewhere in the class, but suppose the current value for count is 10. Then, the new value of count will be 12.
After this, the program executes the line:
bunnyEars(bunnies - 1)
Which translates to:
bunnyEars(1)
Now, basically, you are calling the same method again, but passing in 1 instead of 2.
Once again, the program checks to see that 1 >= 1, which is true. So it goes into the
if-block which, again, increments count by 2. So now, count = 14. Then it calls the
same method again but this time passing in 0.
bunnyEars(0)
Since 0 >= 1 evaluates to false, you the program skips the if-block and continues
execution after the block. So know, you are in the method bunnyEars(), but you have
completely skipped over your "return" statement. But, alas, bunnyEars MUST return an int.
So this is why you must have a return after the block. In your case, bunnyEars(0) returns count2 and the program-execution returns to where you called bunnyEars(0).
Read up on recursive calls. The basic idea of a recursive method is that, inside the recursive method, you must have some case that terminates the recursion (otherwise you will loop forever).
For example, the following code will go on forever:
public int sum(int in)
{
return in + sum(in - 1);
}
This will keep going on forever, because sum(1) will call sum(0) which calls sum(-1).
So, I must have a condition that terminates the recursion:
public int sum(int in)
{
if(in == 0) return 0;
return in + sum(in - 1);
}
Now, I have a terminating-case. So if I call sum(1), it will call sum(0) which returns 0. So my result is 1 + 0 = 1.
Similarily,
sum(2) = 2 + sum(1) = 2 + 1 + sum(0) = 2 + 1 + 0
sum(3) = 3 + sum(2) = 3 + 2 + sum(1) = 3 + 2 + 1 + sum(0) = 3 + 2 + 1 + 0 = 6
Hope this helps!
So as I understand it, your question is why you still need to return count2 if you return count1. The answer is basically 'what happens if you don't enter the if block?'. In that case, without return count2, you wouldn't have a return value, which is what Java is complaining about. If you really don't want two return statements, you could probably do something like:
public int bunnyEars(int bunnies) {
int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
}
return count ;
}
On a side note, this and the code you posted in your question won't work for regression purposes, but the one in your comment does, and there it looks like you have a static variable for count, in which case you could set the return type to void and just print count.
I tried to investigate what will happen if I write some code after the recursive call and here is the code. I tried to trace the code but I didn't get what was going on. I thought the function will be terminated once my program prints the last value for x since the value for x doesn't satisfy the if loop condition. I executed this code, the result wasn't understandable. Any help would be appreciated.
public class Recursive {
public static void main(String []args){
int a=5;
call(a);
}
public static void call(int x) {
System.out.print(x+"\n");
if(x>0) {
x--;
call(x);
}
System.out.print(x);
}
}
Expected output:5 4 3 2 1 0 0
My output: 5 4 3 2 1 0 0 0 1 2 3 4
instead of while, you can try If condition and remove the last print.
public static void call(int x) {
System.out.print(x+"\n");
if (x>0) {
x--;
call(x--);
}
}
You forgot to say what was surprising or confusing, which indicates that you don't understand the problem (hence two downvotes). Here is what I think may be confusing. The decrement operator x-- first returns the value of a variable and then lowers it's value. So if you run
z= 25
dothedoo(z--)
the value inside dothedoo will be 25, not 24. The alternative --x will lower the value first and then return the value.
This is your code.
public static void call(int x) {
System.out.print(x + "\n");
while (x > 0) {
x--;
call(x);
}
}
Lets consider this call stack with an input of x=2
1) call(2)
2) print x // 2
2) x-- (becomes 1)
3) recursive call to call(1) // remember the call(2) is suspended right now.
4) print x //1
5) x -- (becomes 0)
6) recursive call to call(0)// remember the call(2) and call(1) is suspended right now.
7) print x //0
8) x-- (becomes -1)
9) recursive call to call(-1) // breaks the loop since it doesnt match the condition, resumes flow to the suspended call(1) function.
10) refer step 5 for the value of x.
11) breaks the loop for the call(1) function. // resumes call(2) which was suspended.
12) refer step 2 where x is still 1.
13) moves on with another call(1)
14) this results in printing an extra 0; from the call in step 13
Your while loop is messing up the program.
Your variable in the recursion is passed by value, hence your actual
value of x which is caller's value isnt decremented globally in the caller when you do this call(x) the x which is used after
decrementing in your recursive call is a copy of the x that you have
decremented in the caller.
Please refer to this article to understand more on it.
Also, the while loop is notorious here based on the explaination provided in this answer and what you actuall need is an if loop