Question:
How many calls are needed to recursively calculate the 7th Fibonacci value?
So this was a problem given to me and the answer was given to me as 41. Then I went to a professor because I didn't understand it, but I was given another answer. I think it was 25? (don't quote me on that) Then I went to another professor... and he told me the person who gave you this problem should have given you the sample code because there can be multiple ways to write this recursive function which would result in different amounts of calls.
So if this is true can you guys find different recursive functions that would result in a different amount of calls needed to get the 7th value of the sequence?
One way:
static long fibonacciR(int i)
{
if (i <= 1)
return i;
return fibonacciR(i - 1) + fibonacciR(i - 2);
}
Another way:
static final int f[] = {0,1,1,2,3,5,8,13,21,34,55,89,144};
static long fibonacciR2(int i)
{
if (i < f.length)
return f[i];
return fibonacciR2(i-1)+fibonacciR2(i-2);
}
In fact 'another' way is any number of other ways, depending on how big you make the table. When the table has two elements both methods are equal. When it has three there are 25 calls. When 4, 15. And so on.
Yet another way, to get specifically 25 calls:
static long fibonacciR3(int i)
{
if (i == 0)
return 0;
if (i <= 2)
return 1;
return fibonacciR(i - 1) + fibonacciR(i - 2);
}
Related
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.
I am working on a problem that seems to require backtracking of some sort. I have a working recursion method but stackOverFlow happens with larger inputs. Could this be solved with an iterative implementation? I am trying to implement a method that takes in two target values a and b. starting with a = 1 and b = 1, how many "adds" would it take to reach the target a and b values? adds can either make a = a + b or b = b + a, but not both.
for example, if target a = 2 and target b = 1, it takes 1 "add". a=1 & b=1, a = a + b = 2.
public static String answer(String M, String F) {
return answerRecur(new BigInteger(M), new BigInteger(F), 0);
}
public static String answerRecur(BigInteger M, BigInteger F, int its) {
if(M.toString().equals("1") && F.toString().equals("1")) {
return "" + its;
}
else if(M.compareTo(new BigInteger("0")) <=0 || F.compareTo(new BigInteger("0")) <=0) {
return "impossible";
}
String addM = answerRecur(M.subtract(F), F, its +1);
String addF = answerRecur(M, F.subtract(M), its +1);
if(!addM.equals("impossible")) {
return addM;
}
if(!addF.equals("impossible")) {
return addF;
}
return "impossible";
}
Recursive backtracking works by going through all candidate steps, do a step, recurse, undo the step.
This means that if a solution takes N items, ideally the recursion depth will not exceed N.
So: an overflow is not expected, probably too much is tried, or even infinitely recurring.
However in your case a BigInteger might be sufficient large and when using small steps (1) one would have a very recursion depth. And every call creates sufficient much. Better would be int or long instead of BigInteger.
In every call you have two candidates:
M.subtract(F)
F.subtract(M)
You evaluate both, one could stop when a result was found.
Also intelligence (of the math!) is missing: nice would be to prevent too many steps, finding as directed as possible a solution. In general this can be achieved by some way of sorting of the (2) candidates.
How one comes at a smart solution? First the math must be readable, what BigInteger is less. Try some sample solutions by hand, and look for a smart approach to order the attempts.
You can cut the recursion short, assuming keeping M and F positive:
if (M.compareTo(BigInteger.ZERO) <= 0 || F.compareTo(BigInteger.ZERO) <= 0) {
return "impossible";
}
if (M.equals(BigInteger.ONE)) {
return String.valueOf(F.intValue() - 1 + its);
}
if (F.equals(BigInteger.ONE)) {
return String.valueOf(M.intValue() - 1 + its);
}
The same can be done with integer division (and modulo):
if (M.compareTo(F) > 0) {
String addM = answerRecur(M.mod(F), F, its + M.divided(F).intValue());
}
Thinking of an iterative solution actually is possible here despite more than one recursive call, but it would not add to the quality.
Remarks:
by java convention one should use f and m for variable names.
is BigInteger really required? It causes a bit awkward code.
I wanted to do this exercise that professor gave to our class but I don't know how to do it:
Write a method, called first, that returns the most small prime number between 90 and 150.
Well that could be quite easy...if I could use loops like for or similar but i can't. I can just use if, Array, Method and other really basic things, no libraries.
The only 2 solution that i found is to write around 60 IF or just to write
int prime(){
return 97;
}
Please help me to do it or I have to deliver it in this last way :'D
You can do it without traditional "loops" by making a recursive function, a function that calls itself. Here's some pseudo code:
int nearestPrime(int val) {
if (val is prime) {
return val;
} else {
return nearestPrime(val + 1);
}
}
I'm studying for my computer science final and am going back over some of the things that I never quite grasped when we went over them in class. The main thing being recursion. I think I've got the hang of the simple recursion example but am trying to work through one that was on a previous exam and am having trouble figuring out how it should be done.
Here is the question:
Texas numbers (Tx(n)) are defined as follows for non-negative numbers (assume true):
Tx(n) = 10 if n is 0
Tx(n) = 5 if n is 1
Tx(n) = 2*(Tx(n-1) + Tx(n-2) if n >= 2
We are then to write the recursion function for Texas numbers, after making some corrections after the test, here's what I've come up with, I think it's right, but not 100% sure.
public int Tx(int n) {
if(n == 0)
return 10;
else if (n == 1)
return 5;
else
return 2*(Tx(n-1) + Tx(n-2));
}
Then we are asked to computer the value of Tx(5). This is where I'm stuck. If the return statement for the else was simply n-1, I think I'd be able to figure it out, but the n-1 + n-2 is completely throwing me off.
Can anyone explain how this would work, or share some links that have similar examples. I have tried looking this up online and in my textbook but the examples I've found are either so advanced that I have no clue what's going on, or they only deal with something like return n-1, which I already know how to do.
Let's start with Tx(2). n > 1, so we have 2*(Tx(n-1) + Tx(n-2)) which is 2*(Tx(1) + Tx(0)).
But we already know Tx(1) and Tx(0)! So just substitute them in and you get 2*(5 + 10) -> 30. Great, so now we know T(2).
What about T(3)? 2*(Tx(2) + Tx(1)). Nice, we already know these too :) Again, just fill them in to get 2*(30 + 5) -> 70.
You can work forwards to get to Tx(5).
Your code is logically correct, you should just be using == to test equality, a single = is for assignment.
When you run your method, it will work backwards and solve smaller and smaller subproblems until it gets to a point where the answer is known, these are your base cases.
Tx(3)
2* Tx(2) + Tx(1)
2*Tx(1) + Tx(0) (5)
(5) (10)
In order for recursion to work, whatever you are doing each time to break the problem down into smaller problems needs to make some progress towards the base case. If it doesn't, you will just infinitely recurse until your computer runs out of space to store all of the repeated calls to the same function.
public int Tx(int n) {
if(n == 0)
return 10;
else
return Tx(n+1); // n will never reach 0!
}
Tx(1) becomes Tx(2) -> Tx(3) -> Tx(4) -> Tx(5) etc.
Your implementation is good, only one minor mistake - in the conditions you should replace = with == - it's not an assignment - it's a comparison.
By the way, what would you expect your method to return for Tx(-1) ?
You have implemented it right just change = with ==.
If you want to further reduce the time complexity you can store the result in an array global to the function so that your function doesnot compute results again and again for a same number this will only save you some time for large computations.
You can use something like this.
public int tx(int n , int []arr) {
if (arr[n] == 0) {
if (n == 1) {
arr[n] = 10;
}
else if (n == 2) {
arr[n] = 5;
}
else {
arr[n] = 2 * (tx((n - 1), arr) + tx((n - 2), arr));
}
}
return arr[n];
}
See whenever you ask the computer for the value Tx(5) it will call the recursive function and so the program will execute the else part because value of n=5.
Now in the else part 2*(Tx(n-1)+Tx(n-2)) will be executed.
In first iteration it will become 2*((2*(Tx(3)+Tx(2)))+(2*(Tx(2)+Tx(1)))) . The iteration will be continued until the value of n become 0 or 1.
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.