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.
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 am very new to Java (doing a beginners university module) so sorry for the probably silly question. I am trying to verify whether a ragged array is a 'tridiagonal matrix'.
It is valid if it is of length 3 at the first level and of length n − 1, n, and n − 1 at the second level. I intended to come up with a code to firstly verify the length is 3, then find the longest length array within it for n, then finally verify each length.
For whatever reason my code won't compile but I'm not seeing an error message, just a red exclamation mark on the class. I assume this means there are multiple errors. If anyone could point them out it would be a massive help.
static boolean isValidTridiagonal ( double [][] m)
{
if (double [][]=new double [3][])
{
int n = 0;
for(int i = 0; i < m.length; i++)
{
if(m[i].length > n)
{
n = m[i].length;
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
{
return true
}
else
{
return false
}
}
else
{
return false
}
}
Thanks very much!
I agree with Foolish in the comments that it's helpful to use an IDE that can highlight syntax errors and other problems with the code, it really makes a huge difference. Apart from that, another general strategy is to always code in "baby steps": do only the minimal thing to test if the code works, compile and test often. And if you still have troubles, you can always comment out chunks of your code when searching for the offending bits.
Having said that, the errors that I see in your code are:
if (double [][]=new double[3][])
If you want to test the length of the input, you can do if (m.length == 3)
In
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
you're not testing for equality, but rather trying to put the values n-1 etc into m[0].length, which is not going to work. What you probably meant was
if( (m[0].length == n-1) && (m[1].length == n) &&(m[2].length==n-1))
In
return true
you're missing a semicolon. The compiler is whiny about things like that and unless you use an IDE or learn to interpret the compiler error messages, it can be really painful to find such errors.
Finally, of course, the answer by vasste provides a much simpler solution to your actual task, so it's worth looking into that :).
Why do you need all that loops? If all arrays cannot be null, than
static boolean isValidTridiagonal(double[][] m) {
return m.length == 3 && m[0].length == m[1].length - 1 && m[2].length == m[0].length;
}
You're missing a few braces at the end but, judging from your indentation, you just forgot to copy them.
You're missing semicolons from the end of the return lines.
The condition within this if statement if (double [][] = new double [3][]) is not a valid expression. You simply want to evaluate the length, which you can do like if (m.length == 3). You did the same thing later on.
The line including (m[0].length = n-1) && (m[1].length = n) && (m[2].length=n-1) is not valid because you are performing assignment (=) in all three cases. An equality check is the double equals operator ==.
You do not return a value in every case. You can fix this by adding return false; after the closing brace of your first if statement, i.e. the last line of the function.
This is enough to get your code to compile. As mentioned in another answer though, your logic is confusing and without actually tracing it through I would speculate that it will not work as you would expect.
If I have understood your requirements correctly, you can rewrite the entire function as:
static boolean isValidTridiagonal ( double [][] m)
{
return m.length == 3 &&
m[0].length + 1 == m[1].length &&
m[2].length + 1 == m[1].length;
}
A proper IDE - Netbeans, Eclipse, etc. - will give you fairly descriptive error messages to show you where you've gone wrong.
This is basically completely stylistic but I wish someone had pointed this out to me earlier. If you ever find yourself writing code in this form:
if( (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1))
{
return true;
}
else
{
return false;
}
know that you can save yourself so many lines without losing any readability by instead writing:
return (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1);
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);
}
I'm trying to make a method that will tell me weather or not it is true or false that a number is prime. here's the code:
class prime
{
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
prime (a, b-1) ;
}
else
{
return true;
}
}
public static void main (String[] arg)
{
System.out.println (prime (45, 45)) ;
}
}
when i try to compile this i get this error message:
prime.java:23: missing return statement
}
^
1 error
I could be misinterpreting what the error message is saying but it seems to me that there isn't a missing return statement since i have a return statement for every possible set of conditions. if a is 0 then it returns false, if it isn't then it checks to see if a is dividable by b if it is then it returns if not then if b is greater than 1 it starts over again. if b isn't greater than 1 it also returns.
Also it seems a bit messy to have to
make this method take two ints that
are the same int.
What is wrong with my syntax/ why am i getting the error message? Is there a way to make it so that the method that i use in main only has to take one int (perhaps another method splits that int into two clones that are then passed to public static boolean primeproper?
or is there a more effective way of
going about this that i'm missing
entirely?
In your prime function, there are four possible code paths, one of which doesn't return anything. That is what the error message is complaining about. You need to replace:
prime (a, b-1) ;
with:
return prime (a, b-1) ;
in the else if (b>1) case.
Having said that, this is actually not a good way to calculate if a number is prime. The problem is that every recursive call allocates a stack frame and you'll get into serious stack overflow problems if you're trying to work out whether 99,999,999 is a prime number?
Recursion is a very nice tool for a certain subset of problems but you need to be aware of the stack depth. As to more efficient solutions, the are many tests you can carry out to determine a number is not prime, then only check the others with a brute force test.
One thing you should be aware of is to check divisibility against smaller numbers first since this will reduce your search scope quicker. And don't use divide where multiply will do, multiplication is typically faster (though not always).
And some possibly sneaky tricks along the lines of:
every number other than 2 that ends in 2, 4, 6, 8 or 0 is non-prime.
every number other than 5 that ends in 5 is non-prime.
Those two rules alone will reduce your search space by 60%. Assuming you get your test number as a string, it's a simple matter to test the last digit of that string even before converting to an integral type.
There are some more complex rules for divisibility checks. If you take a multiple of 9 and sum all the digits to get a new number, then do it again to that number, then keep going until you have a single digit, you'll find that it's always 9.
That will give you another 10% reduction in search space albeit with a more time-expensive check. Keep in mind that these checks are only advantageous for really large numbers. The advantages are not so great for, say, 32-bit integers since a pre-calculated bitmap would be much more efficient there (see below).
For a simplistic start, I would use the following iterative solution:
public static boolean prime (int num) {
int t = 2;
while (t * t <= num) {
if ((num % t) == 0) {
return false;
}
t++;
}
return true;
}
If you want real speed in your code, don't calculate it each time at all. Calculate it once to create a bit array (one of the sieve methods will do it) of all primes across the range you're interested in, then simply check your values against that bit array.
If you don't even want the cost of calculating the array every time your program starts, do it once and save the bit array to a disk file, loading it as your program starts.
I actually have a list of the first 100 million primes in a file and it's easier and faster for me to use grep to find if a number is prime, than to run some code to calculate it :-)
As to why your algorithm (fixed with a return statement) insists that 7 is not prime, it will insist that every number is non-prime (haven't checked with negative numbers, I'm pretty sure they would cause some serious problems - your first check should probably be if (a < 1) ...).
Let's examine what happens when you call prime(3,3).
First time through, it hits the third condition so calls prime(3,2).
Then it hits the second condition since 3 % (2-1) == 0 is true (N % 1 is always 0).
So it returns false. This could probably be fixed by changing the third condition to else if (b>2) although I haven't tested that thoroughly since I don't think a recursive solution is a good idea anyway.
The following complete code snippet will do what you need although I appreciate your curiosity in wanting to know what you did wrong. That's the mark of someone who's actually going to end up a good code cutter.
public class prime
{
public static boolean isPrime (int num) {
int t = 2;
while (t * t <= num) {
if ((num % t) == 0) {
return false;
}
t++;
}
return true;
}
public static void main (String[] arg)
{
System.out.println (isPrime (7)) ;
}
}
You seem to be under the impression that because the recursion will eventually find a base-case which will hit a return statement, then that return will bubble up through all of the recursive calls. That's not true. Each recursive call must pass out the result like this:
return prime(a, b - 1);
If b is larger than 1, your function won't return anything.
May it be return prime (a, b-1) ; ?
To improve efficiency, think more about your conditions. Do you really need test every factor from 2 to N? Is there a different stopping point that will help tests of prime numbers complete more quickly?
To make a better API, consider making the recursive method private, with a public entry point that helps bootstrap the process. For example:
public static boolean prime(int n) {
return recurse(n, n);
}
private static boolean recurse(int a, int b) {
...
}
Making a method private means that it can't be called from another class. It's effectively invisible to users of the class. The intent here is to hide the "ugly" extra parameter by providing a public helper method.
Think about the factors of some composite numbers. 10 factors to 5×2. 12 factors to 6×2. 14 factors to 7×2. Now think about 25. 25 factors to 5×5. What about 9? Do you see a pattern? By the way, if this isn't homework, please let me know. Being this didactic is hard on me.
In answer to why 7 isn't working, pretend you're the computer and work through your logic. Here's what you wrote.
class prime
{
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
// Have to add the return statement
// here as others have pointed out!
return prime(a, b-1);
}
else
{
return true;
}
}
public static void main (String[] arg)
{
System.out.println (prime (45, 45)) ;
}
}
So let's start with 7.
if(7 == 0) // not true, don't enter this block
else if(7 % 6 == 0) // not true
else if(7 > 1) // true, call prime(7, 6)
if(7 == 0) // not true, don't enter this block
else if(7 % 5 == 0) // not true
else if(6 > 1) // true, call prime(7, 5)
if(7 == 0) // not true, don't enter this block
else if(7 % 4 == 0) // not true
else if(5 > 1) // true, call prime(7, 4)
... keep going down to calling prime(7, 2)
if(7 == 0) // not true, don't enter this block
else if(7 % 1 == 0) true, return false
When you get down to calling prime(n, 2), it will always return false because you have a logic error.
Your recursive method must return a value so it can unroll.
public static boolean prime (int a, int b)
{
if (a == 0)
{
return false;
}
else if (a%(b-1) == 0)
{
return false;
}
else if (b>1)
{
return prime (a, b-1) ;
}
else
{
return true;
}
}
I might write it a different way, but that is the reason that you are not able to compile the code.
I think the original question was answered already - you need to insert return in the body of else if (b>1) - I just wanted to point out that your code still will crash when given 1 as the value for b, throwing an ArithmeticException since a%(b-1) will be evaluated to a%0, causing a division by zero.
You can avoid this by making the first if-statement if (a == 0 || b == 1) {}
This won't improve the way the program finds primes, it just makes sure there is one less way to crash it.
Similar to #paxdiblo's answer, but slightly more efficient.
public static boolean isPrime(int num) {
if (num <= 1 || (num & 1) == 0) return false;
for (int t = 3; t * t <= num; t += 2)
if (num % t == 0)
return false;
return true;
}
Once it is determined that the number is not even, all the even numbers can be skipped. This will halve the numbers which need to be checked.