Java Recursive Method how does it work? - java

I'm relatively new to Java programming and I've just started learning recursion, but I can't seem to figure out how this method works in my head.
private static int mystery(int w) {
{
if (w < 0) return 0;
int x = mystery (w-2);
return w - x;
}
}
Whenever a variable like 100 is put in, it outputs 50. When 200 is input, it outputs 100. When 2 is input, it outputs 2. When 25 is input, 13 is output. I'm not sure how this method works, and I'm trying to wrap my head around it.
The way I currently view it, if you put in 100, it'll bypass the first return statement since it is greater than 0.
when it gets to the second line, it'll do 100-2, which brings in 98, then goes to the third line and does 100 - 98 = 2. Which is then returned to the original call.
I know I'm messing up on the second line of the method where the mystery (w-2) is. I assume it would bring back the result of w-2 to the beginning of the method again, and it would continue to do the method over and over again until w is smaller than 0, which should output 0 again regardless of the answer. But that's not what happens, and I don't know why.
Can anyone explain what is going on here?

What you are missing is that on the second line it doesn't just do w - 2, but calls itself with w - 2. It doesn't go further until the call returns. And the second call calls itself if w isn't < 0 and so on until you reach value lower than 0 and then return. The execution will go like this, if you visualize it:
mystery(10)
> skip first line
> x = mystery(8)
> skip first line
> x = mystery(6)
> skip first line
> x = mystery(4)
> skip first line
> x = mystery(2)
> skip first line
> x = mystery(0)
> skip first line
> x = mystery(-2)
> return 0
> return 0 - 0 (0)
> return 2 - 0 (2)
> return 4 - 2 (2)
> return 6 - 2 (4)
> return 8 - 4 (4)
> return 10 - 4 (6)
With example of w = 10. I hope you understand it better now.

private static int mystery(int w) {
{
if (w < 0) return 0;
int x = mystery (w-2);
return w - x;
}
}
Let's imagine that we call mystery(3). What happens? w<0) is false, so we don't return 0. In the next line, we call some function called mystery using the value 3-2=1 as its argument.
Despite the fact that this function we've called happens to be the same one we've just called, it's still an ordinary function call, and it returns a value. It does this by calling the function called mystery, this time using the value -1 as the argument. And this time w<0 is true, so we just return 0. Now we're back in the second call to mystery, and we've set x = 0. So that call returns w - 0 = 1. That puts us back in the first call, and now x = 1, so we return w-x = 3-1 = 2.
You might want to take a few minutes and work through this using w=4 and see what you get - this will help you understand how the recursive calls work.
After you've done this, I suggest you add a print statement or two in the function to tell you where you are and what's happening, and that'll also help - but do it on paper first.

The two given answers are excellent. Both focus on the way how to get a grasp of what recursion is. The problem with recursion is, that it is so unnatural to one who do not know what recursion is, or do not know someone who does. It's like a snake eating itself again and again.
The best way to understand recursion is to write down the calls to a recursive method, by noying the current state when it's called, and after the call write the result back. You stack up the calls and that's also the way to not used recursion at all.
So do not try too hard to understand recursion at first but first focus on the program flow. If you have seen enough recursions, it will come to you.

Related

Can't pass big test case while finding square root of int X in Java without built-in function [duplicate]

I'm trying to write a Java program to calculate the square root of an integer x, without using in-built functions like Math.pow() . This is the approach I tried -
class Solution {
public int mySqrt(int x) {
if(x==0 || x==1)
return x;
// if(x>=2147395600)
// return 46340;
int i;
for(i=1 ; i*i<=x ; i++) {}
return i-1;
}
}
Without the commented part, I start getting errors if x is in the range 2147395600 <= x <= 2^31-1 (which is the upper limit of an int's value range in Java). For instance, for the input x=2147395600, the expected output is 46340 but the actual output is 289398. Why is this happening? Thanks to all in advance.
PS - I am aware there are other (better) methods to solve this problem, but I'd really like to know why this code behaves this way.
Since 46340 * 46340 = 2147395600, when i=46340, x=2147395600 and you reach the condition i*i<=x it evaluates to true since 2147395600 = 2147395600. So the loop counter will incremnet by 1 and in the next iteration we will get i=46341 and i * i will cause an overflow - 46341*46341 = -2147479015.
The loop condition will still be true, since -2147479015 <= 2147395600, and the loop will not stop.
You can replace the <= with =, and check for edge cases that may occur now.

Recursive solution to counting the number of ways you can go up a staircase

I'm trying to solve the problem of "count ways to reach the nth step in a staircase" with recursion. When given a number of stairs to climb, I have to calculate the number of ways to climb taking either 1 or 2 steps at a time. For example, if there are 4 stairs, we would return 5 since we would have:
* 1 1 1 1
* 1 1 2
* 1 2 1
* 2 1 1
* 2 2
My code is currently throwing a stack overflow exception:
public static int countWaysToClimb(int stairs) {
return countWaysToClimbHelper(stairs, 0, 0);
}
public static int countWaysToClimbHelper(int sumNeeded, int currentSum, int possibleCombos) {
// base - we will reach this base multiple times
if (sumNeeded == currentSum) {
possibleCombos++;
// if we already found a combo, we need to reset the sum
countWaysToClimbHelper(sumNeeded,0,possibleCombos);
}
else if (currentSum > sumNeeded) {
return 0;
}
// recurse - add 1 and then add 2
countWaysToClimbHelper(sumNeeded,currentSum+1,possibleCombos);
countWaysToClimbHelper(sumNeeded,currentSum+2,possibleCombos);
return possibleCombos;
}
Thank you!
There are some issues in your code:
Base case (condition that terminates the recursion) is incorrect. Every branch of recursive calls spawn new branches when it hits the condition if (sumNeeded == currentSum) is meat instead of returning the number of combinations. You created an infinite recursion that inevitably leads to a StackOverflowError. You have to place a return statement inside the curly braces after the first if in your code. And comment out the first recursive call (with 0 sum passed as an argument) you'll face the second problem: for any input, your code will yield 0.
Results returned by recursive calls of your method countWaysToClimbHelper() are omitted. Variable possibleCombos isn't affected by these calls. Each method call allocates its own copy of this variable possibleCombos on the stack (a memory aria where JVM stores data for each method call), and their values are not related anyhow.
you actually don't need to pass the number of combinations as a parameter, instead you have to return it.
Before moving further, let me recap the basics of recursion.
Every recursive method should contain two parts:
base case - that represents a simple edge-case for which the outcome is known in advance. For this problem, there are two edge-cases:
sumNeeded == currentSum - the return value is 1, i.e. one combination was found;
sumNeeded > currentSum - the return value is 0.
recursive case - a part of a solution where recursive calls a made and when the main logic resides. In your recursive case you need to accumulate the value of the number of combination, which will be the sum of values returned be two branches of execution: take 1 step or 2 steps.
So the fixed code might look like that:
public static int countWaysToClimb(int stairs) {
return countWaysToClimbHelper(stairs, 0);
}
public static int countWaysToClimbHelper(int sumNeeded, int currentSum) {
// base - we will reach this base multiple times
if (sumNeeded == currentSum) {
return 1;
} else if (currentSum > sumNeeded) {
return 0;
}
// recurse - add 1 and then add 2
int possibleCombos = 0;
possibleCombos += countWaysToClimbHelper(sumNeeded,currentSum + 1);
possibleCombos += countWaysToClimbHelper(sumNeeded,currentSum + 2);
return possibleCombos;
}
Note:
This code could be enhanced further. The whole logic can be implemented inside the countWaysToClimb() without using a helper-method. For that, instead of tracking the currentSum you need to subtract the number of steps from the sumNeeded when the method is called recursively.

How does the memory stack look for back to back recursive calls?

I am trying to understand the concept of recursion. I understand how it works if there is one recursive statement in the code (example factorial)
I dont understand how code like this to calculate the depth of a binary tree would work:
public int getDepth(Node root)
{
if ( root == null) return 0;
int left = getDepth(root.left);
int right = getDepth(root.right);
if (left > right)
return left + 1;
else
return right + 1;
}
I see why this works but not how. Can someone explain to me how the second recursive call (getDepth(root.right)) works? What would this code look like in the memory? When getDepth(root.left) is recursive called does that stack ever go to the if statement at the every bottom?
What happens is that each consecutive call to getDepth is completely separate and thus the bound variables are separate and it follows it's arguments and is oblivious that it's called from a version of itself with different arguments.
When you do getDepth(null) you get 0 since it's the very base case on the first line. However if you send it getDepth(new Node(null, null)) it will call getDepth(root.left) which is the same as getDepth(null) and turns into 0 for both left and right and the result is 0 + 1.
If you would bind the previous node to a variable node and try getDepth(new Node(node, node)) it will do both left and right again where both of them would be the answer of the previous test 1. The result would be 1 + 1, thus 2.
You can continue like this and just assume the result based on the previous calculations. By looking from a complex argument you need to imagine that each consecutive recursion starts fresh with it's arguments and that follows the same pattern. When a result is passed back the caller continues to the next line. In a tree structure like:
1
/ \
2 3
/\ /\
4 5 6 7
I just numbered the nodes and not included null nodes. You'll see the execution goes in this order. Identation indicates stack depth / how many calls are waiting to be resumed.
getDepth(1)
getDepth(2) // left
getDepth(4) // left
getDepth(null) // left base
getDepth(null) // right base
return 0
getDepth(5) // right
getDepth(null) // left base
getDepth(null) // right base
return 0
return 0 + 1;
getDepth(3) // right
getDepth(6) // left
getDepth(null) // left base
getDepth(null) // right base
return 0
getDepth(7) // right
getDepth(null) // left base
getDepth(null) // right base
return 0
return 0 + 1;
return 1 + 1;
return 2 + 1;
Try to trace the execution if the tree consisted of only a single node (just the root node).
The stack would look something like this when getDepth(root.left) is called:
--->getDepth(root.left) //this will return 0 immediately, and will be popped of the stack
getDepth(root) // this is your entry point
once, getDepth(root.left) returns, the stack looks like this:
--->getDepth(root) // this is your entry point
then the method at the top of the stack now will continue it's execution from where it was (it will now call getDepth(root.right), and the stack will look like this:
--->getDepth(root.right) //this will return 0 immediately, and will be popped of the stack
getDepth(root) // this is your entry point
again, once getDepth(root.right) returns, it will be popped off the stack and the calling method will continue it's execution and will then execute the last if statement.
The same pattern of execution will be followed for a tree with multiple nodes: eventually the recursive method calls will return (unless there is an exception) and the calling method will continue it's execution from the next statement.

What is wrong with this recursive method? (java)

The method is for a calculator and is supposed to return log2(n). All of the methods used (monus which is minus spelled wrong) power, ect) are written correctly. s(n) just adds one to n and p(n) subtracts one.
when I call the method in the main it gets the remainder right, but always returns 0 for the answer. this confuses me. I am sure it has to do with the fact that i am reinitializing answer to 0 each time the method is called but shouldn't that not matter because it is always going to get set to x before it returns anything?
x is a private static variable that has been set to 0 outside of the method.
public static long v(long n)
{
long answer =0;
if (power(2,x) > n)
{
x = p(x);
setRemainder(monus(n,power(2,x)));
answer = x;
}
else if(power(2,x) ==n)
{
setRemainder(0);
answer = x;
}
else
{
x = s(x);
v(n);
}
x=0;// reset x so it can be used again.
return answer;
}
can anyone help me?
You should change the line:
v(n);
to:
answer = v(n);
Right now, if the last else block is executed, the answer variable is not changed - so it's still 0.
As stated in the comments you make the recursive call in the else statement but don't assign this to anything when the recursive call returns.
Consider this:
On your first call: x = 0 so probably going to the else statement and enter the recursion. At some point of recursion one of your conditional statements will be true and in this case answer is returned but not assigned in the way back down the stack of recursive calls.
So would look like this:
1: v(n) // this calls v(n) again
2: v(n) returns answer = x // this returns an answer
1: returns answer = 0 // now the return falls down a level to where the recursive
// call was and the answer is lost as was not assigned

Counting in recursion calls

I need to write a method that checks how many possible ways there are to finish a grid (a 2D array).
the movement inside the grid is like this:
start with [0][0] take the number inside there (for instance 14) then go to either
[array.[0][0]%10][array.[0][0]/10] or [array.[0][0]/10][array.[0][0]%10]
for our example:
[1][4] or [4][1]
until you get to the end of the array (bottom right corner).
I can get to the end of the array (all possible ways) - my problem is to count how many times I actually finished the array - I can not use a variable outside of the method, and the method has to be recursive.
this is the code :
private static int howMany(int[][] array, int y, int x, int count) {
if(y+(array[y][x]%10) < array.length && x+(array[y][x]/10)< array[y].length && array[y][x]!=0) {
System.out.println("["+y+"]["+x+"] is: "+array[y][x]);
howMany(array, y+(array[y][x]%10), x+(array[y][x]/10),count);
}
if(y+(array[y][x]/10) < array.length && x+(array[y][x]%10)< array[y].length && array[y][x]!=0) {
System.out.println("["+y+"]["+x+"] is: "+array[y][x]);
howMany(array, y+(array[y][x]/10), x+(array[y][x]%10),count);
}
if(y==array.length-1 && x==array[y].length-1) count++;
return count;
}
this is obviously wrong and will return what count was in the first place, I tried many other ways but to no avail...
here's the full class (with an array to test):
link to full class
edit: a big Thanks to everyone for their help!
The count is already returned from each call to howMany. I think you just need to save it:
count = howMany(array, y + (array[y][x] % 10), x + (array[y][x] / 10), count);
Do this inside both if blocks. I made this change in your linked code and got the expected result (3).
You are already on the right track, since your method signature returns an int. You should define a variable to hold the count, increment it for the primary recursive call, and add to it the result of the recursive method itself. Passing the count into the each recursive call is unnecessary and should be removed.
Return 1 if you've reached the end of the array (bottom right corner) and 1+howMany(array, newY, newX) otherwise. You don't need to keep the count and pass it every time. The function will work so:
1 + returned value of 2nd call =
1 + 1 + returned value of 3rd call =
1 + 1 + 1 + returned value of 4th call =... and so on.
Finally as result you'll get number of calls which is what you want.

Categories