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!
CodePudding user response:
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 aStackOverflowError
. You have to place a return statement inside the curly braces after the firstif
in your code. And comment out the first recursive call (with0
sum passed as an argument) you'll face the second problem: for any input, your code will yield0
. - Results returned by recursive calls of your method
countWaysToClimbHelper()
are omitted. VariablepossibleCombos
isn't affected by these calls. Each method call allocates its own copy of this variablepossibleCombos
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 is1
, i.e. one combination was found;sumNeeded > currentSum
- the return value is0
.
- 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 thecurrentSum
you need to subtract the number of steps from thesumNeeded
when the method is called recursively.