I am trying to understand this recursive method but even with a debugger I couldn't come up to something that makes sense to me so i hope someone here is motivated to explain me what is going on here. I know how recursion works basically but the way this method is written down troubles me.
I know the conditional operator in java and I worked out a new code but still I don't understand it, so what I expect here is.
What is the result for m(5) AND m(15). How did you calculate it? Thanks
Edit after the answers. I made a table with my results for future readers
m(n)::|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|...
result|0|0|1|1|1|2|3|4|6|9|13|19|28|41|60|88|...
I checked only the result of 15 with my program.
public class practice {
/**
* Try to understand the way this works
* #param n
* #return
*/
static long m(long n) {
return n <= 1 ? 0 : n == 2 ? 1 : m(n - 1) + m(n - 3);
}
/**
* This is what i tried so far.
* #param n
* #return
*/
static long ma(long n) {
System.out.println("Method called");
System.out.println("N is: " + n);
if (n <= 1) {
System.out.println("N<=1: " + n);
System.out.println("0 is returned");
return 0;
} else if (n == 2) {
System.out.println("N==2: " + n);
System.out.println("1 is returned");
return 1;
} else {
System.out.println("Inside ELSE, N is: " + n);
return ma(n - 1) + ma(n - 3);
}
}
public static void main(String[] args) {
ma(15);
}
}
Wrote it this way to make it more understandable:
m(0) = 0
m(1) = 0
m(2) = 1
m(n) = m(n - 1) + m(n - 3) // n >= 3
When we know the values for m(0), m(1) and m(2), we can calculate any m(n), where n >= 3, using m(n - 1) + m(n - 3). For any negative input, the result is 0.
For example:
m(3) = m(3 - 1) + m(3 - 3) = m(2) + m(0) = 1 + 0 = 1
m(4) = m(4 - 1) + m(4 - 3) = m(3) + m(1) = 1 + 0 = 1
m(5) = m(5 - 1) + m(5 - 3) = m(4) + m(2) = 1 + 1 = 2
And so on...
Pencil and paper are you friends.
There are 3 cases (two of them are base conditions)
if n <= 1 then return 0
if n == 2 then return 1
else recursive call to m(n-1) + m(n-3)
So you know that on every recursive call we are approaching one of the base conditions.
Here is a stack trace of what happens on m(5)
m(5)
m(4) + m(2)
m(3) + m(1) return 1
m(2) + m(0) return 0
return 1 return 0
Adding all the returns gives 1 + 0 + 0 + 1 which is 2
So
m(5) == 2
Method m in pseudo code. (this is some kind of scala/python mash up)
def m (number n)
if (n <= 1) 0
else if (n == 2) 1
else m(n - 1) + m(n - 3)
Looking at this you can see that anything <= 2 is a terminal operation, returning 0 or 1 based on the input. If n is > 2, the fun begins. Take for example n=3. Since 3 is greater than 2, we need to run the third if. When we look at that line we see that we nee to return m(n - 1) + m(n - 3). Plugging n = 3 in, it looks like this: m(3 - 1) + m(3 - 3), or, more simplified, like this: m(2) + m(0). This will now terminate with 1 because neither 2 or 0 for n will result in more calling of m.
So now we have something we understand we can now workout what m(15) and m(5) will return.
I will only work it out for 5 since the call stack for 15 would be way to long
m(5)
/ \
m(5-1) + m(5-3)
/ \ |
m(4-1) + m(4-3) |
/ \ | |
m(3-1) + m(3-3) | |
| | | |
1 + 0 + 0 + 1
2
Hope it helps!
m(5) = m(4)+m(2) // 5>2, so the third condition
m(4) + m(2) = m(3)+m(1) + 1 // 4>2, so the third condition
m(3) + m(1) + 1 = m(2)+m(0) + 0 + 1 // 3>2, so the third condition
m(2) + m(0) + 0 + 1 = 1 + 0 + 0 + 1 = 2
Now, between transformations, m(2) s instantly replaced with 1, and m(n<=1) is instantly replaced with 0. This is how you can analyze this on paper. Computer, however, would wirst calculate m(4) before calculating m(2) and adding the results in the first line - this happens because of order of poerations within the recursive functions.
Related
I'm new to recursion and don't understand how it works.
This was a classwork problem that had the answer 18, but I don't understand how. From what I know, this should return 6 + 5 + 4 + 3 (3 + m-1 on the recursive line)?
Are the subtraction signs not indicative of subtraction? (assuming that m = 5)
public int test(int m)
{
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
return value;
}
6 + 5 + 4 + 3 (3 + m-1 on the recursive line)? Are the subtraction
signs not indicative of subtraction?
No the +3 will happen for every one of the recursive calls, actually what your function is doing is given the value of (m times 3) + 3.
So for m=5 the recursive calls will be like:
Is m = 0 ? No so let us called recursively:
test(4) + 3
m = 4; then test(3) + 3 + 3
m = 3; then test(2) + 3 + 3 + 3
m = 2; then test(1) + 3 + 3 + 3 + 3
m = 1; then test(0) + 3 + 3 + 3 + 3 + 3
m = 0; then exit with 3 + 3 + 3 + 3 + 3 + 3
Hence, for m=5 you get 18.
A side-note you can use the ternary operator to simplify your method to:
static public int test(int m) {
return (m == 0) ? 3 : test(m - 1) + 3;
}
For visualizing what happens, scatter the code with messages:
public int test(int m)
{
System.out.println("entering test("+m+")");
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
System.out.println("returning "+value+" from test("+m+")");
return value;
}
Of course this is just the minimal program, you could also show which branch of the if was taken, m-1, and so on.
JavaScript equivalent, so it can run here in the browser:
function test(m) {
console.log("entering test(" + m + ")");
var value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
console.log("returning " + value + " from test(" + m + ")");
return value;
}
console.log("result: "+test(3));
On the longer run it is a good idea to learn using the debugger of the environment you are using. Among other things, debuggers can step through code line-by-line.
Why is it that inside a for loop and calling a recursive function results to the time complexity of O(2^N) not O(N 2^N) of this code below. Basing on the book CTCI.
void allFib(int n){
for (int i = 0; i < n; i++) {
System.out.println(i + ": "+ fib(i));
}
}
int fib(n){
if (n <= 0) return 0;
else if (n == 1) return 1;
return fib(n - 1) + fib(n -2);
}
Think of your recursive function as computing values in a tree.
fib(n)
/\
/ \
fib(n-1) fib(n-2)
If you look carefully for n = 2, there are 3 values to be computed which is 2^(1+1) - 1 = 3 where 1 here is the height of the tree as in2^(h+1)-1
for n = 3, the height is h = 2
for n = 4, the height is h = 3
For all n, you need to add all of those:
2^2 - 1 + 2^3 - 1 + 2^4 - 1 + ....2^n - 1 -> is of the order of 2^(n+1)
Hence you get O(2^n)
public static int wacky (int x , int y){
if(x <= 1){
return y;
}
else{
return wacky(x - 1, y - 1) + y;
}
}
I had a test a while but I still don't know how to do a recursion step by step and I remember this question by memory and I guess on the test thinking that you maybe calculate this way...
public static = 4 + 6 + 1 + 4 + 4 - 1 + 6 - 1 + 6
but was not of the answer choice I realize i was doing something wrong...
my teacher doesn't help me and don't even care I try to get help but he does not how to explain this...
When you call a function recursively, they add the new function to a stack until have a final result (return). When it occurs, you go back return by return in the stack.
An Execution example:
First Round wacky(4, 6):
4 <= 1? No, so call wacky(4 - 1, 6 - 1)
Second Round wacky(3, 5):
3 <= 1? No, so call wacky(3 - 1, 5 - 1)
Third Round wacky(2, 4):
2 <= 1? No, so call wacky(2 - 1, 4 - 1)
Fourth Round wacky(1, 3):
1 <= 1? Yes
return 3;
return 3 + 4;
return 3 + 4 + 5;
return 3 + 4 + 5 + 6;
Why not let Java tell you what is going on? Insert some print statements so you can see the values when the code runs:
private static int indent = 1;
public static int wacky(int x , int y) {
System.out.printf("%" + (indent++ * 2) + "swacky(%d, %d)%n", "", x, y);
int result;
if (x <= 1)
result = y;
else
result = wacky(x - 1, y - 1) + y;
System.out.printf("%" + (indent-- * 2) + "s-> %d%n", "", result);
return result;
}
Test
wacky(4, 6);
Output
wacky(4, 6)
wacky(3, 5)
wacky(2, 4)
wacky(1, 3)
-> 3
-> 7
-> 12
-> 18
I am doing exercises with algebraic formulas to practice the use of recursion in Java.
I am trying to write a method that returns the result of n + (n - 3) + (n - 6) + (n - 9) ... + 0.
For example, when n = 7, the result should be 12.
When n = 10, the result should be 22.
So far, this is what I have:
public static int sumDownBy3(int n)
{
if(triSum <= 0)
{
return sum;
}
sum = n;
triVar += 3;
triSum = (n - triVar);
return sumDownBy3(n + triSum);
}
However, when I compile and run it, it does not return the expected result.
How may I fix this method to correctly apply the formula I am trying to emulate?
So, here are a few tips to hopefully get you going considering the comments by childofsoong and Jonny Henly.
What you are looking for is simply:
f(n) = n + f(n-3) for n > 0.
Your recursive function should just check if n is <= 0. If it is, return 0. Else return the variable n + another call to your function with n-3.
Hope this helps without giving too much away.
Since this isn't an assignment, just practice, then here is a working solution based off the information given in your question. This solution works for all n, however n <= 0 will always return 0.
public static int sumDownBy3(int n) {
if (n <= 0) {
return 0;
}
return n + sumDownBy3(n - 3);
}
Instead of having an extra parameter or global/class variables keeping track of the sum, this example just uses the stack to keep track of the sum. One downside to this approach is that for a very, very large number the stack could overflow and/or the program could lock up.
Output:
sumDownBy3(7) = 12
sumDownBy3(10) = 22
sumDownBy3(9) = 18
Breakdown for sumDownBy3(10):
sumDownBy3(10): 10 !<= 0 -> return 10 + sumDownBy3(10 - 3)
sumDownBy3( 7): 7 !<= 0 -> return 7 + sumDownBy3( 7 - 3)
sumDownBy3( 4): 4 !<= 0 -> return 4 + sumDownBy3( 4 - 3)
sumDownBy3( 1): 1 !<= 0 -> return 1 + sumDownBy3( 1 - 3)
sumDownBy3(-2): -2 <= 0 -> return 0
So 0 + 1 + 4 + 7 + 10 ='s 22
Hello guys I have something that my brain is having a hard time trying to figure out.
My homework is to have "x" bunnies. It recursively calculates the total number of bunny ears.
The even numbered bunnies have the normal two ears, the odd numbered bunnies have 3 ears, but every 5th bunny has 1 ear. My code is complete and work... Here it is...
import java.util.*;
public class bunnies
{
public static int y;
public static void main(String[] args)
{
y = 0;
System.out.println(BunnyEars(3));
}
public static int BunnyEars(int x)
{
if ((x % 5) == 0 && x != 1 && x != 0)
return 1 + BunnyEars(x - 1);
else if ((x % 2) == 0 && x != 0 )
return 2 + BunnyEars(x - 1);
else if ((x % 2) != 0 && x != 0)
return 3 + BunnyEars(x - 1);
else
return 0;
}
}
My question is, how in the world does the first number of ears accumulate to the second number of ears and so on?
I was thinking naming a global variable for int y = 0;
and then
if ((x % 5) == 0 && x != 1 && x != 0)
y += 1;
else if ((x % 2) == 0 && x != 0 )
y += 2;
else if ((x % 2) != 0 && x != 0)
y += 3;
else
return 0;
return y + BunnyEars(x -1);
I think this makes more sense because y is accumulating but it doesn't.
Can you guys please explain how the other one accumulates and not y?
THanks!
Here's your method:
public static int BunnyEars(int x)
{
if ((x % 5) == 0 && x != 1 && x != 0)
return 1 + BunnyEars(x - 1);
else if ((x % 2) == 0 && x != 0 )
return 2 + BunnyEars(x - 1);
else if ((x % 2) != 0 && x != 0
)
return 3 + BunnyEars(x - 1);
else
return 0;
}
Here's a hypothetical example call:
BunnyEars(7)
This then becomes
return 3 + BunnyEars(6)
Which becomes
return 3 + 2 + BunnyEars(5)
return 3 + 2 + 1 + BunnyEars(4)
return 3 + 2 + 1 + 2 + BunnyEars(3)
return 3 + 2 + 1 + 2 + 3 + BunnyEars(2)
return 3 + 2 + 1 + 2 + 3 + 2 + 3 + BunnyEars(0)
return 3 + 2 + 1 + 2 + 3 + 2 + 3 + 0
return 16
Suggested improvement to the code: Add a guard clause to the beginning:
if (x == 0) return 0;
Then you can remove all of the && x != 0s in the if statements. This will clean up the code a lot.
You also have lots of extraneous parenthesis - (x % 2) == 0 is the same as x % 2 == 0.
Improved code:
public static int BunnyEars(int x)
{
if (x < 0) throw new IllegalArgumentException("Bunnies cannot be negative"); // handle bad input
if (x == 0) return 0;
if (x % 5 == 0) // no need for `&& x != 1` because 1 % 5 isn't 0 anyway
return 1 + BunnyEars(x - 1);
else if (x % 2 == 0)
return 2 + BunnyEars(x - 1);
else if (x % 2 != 0)
return 3 + BunnyEars(x - 1);
}
I was thinking naming a global variable for int y = 0 and then
No, global variable should not be used there (although having a local variable could give you slightly more clarity):
if (x == 0) return 0; // Zero bunnies --> zero ears
int y = 0; // Variable y represents the number of ears that bunny number x has
if ((x % 5) == 0 && x != 1 && x != 0)
y = 1;
else if ((x % 2) == 0 && x != 0 )
y = 2;
else if ((x % 2) != 0 && x != 0)
y = 3;
return y + BunnyEars(x -1);
The trick to this (and any other) recursive function is realizing that there's more than one x. Since the function calls itself with a different argument, so each invocation has its own x.
Here is how the sequence of calls and returns looks:
BunnyEars(x==6)
Compute y for x==6 // That's 2
Call BunnyEars(x==5)
Compute y for x==5 // That's 1
Call BunnyEars(x==4)
Compute y for x==4 // That's 2
Call BunnyEars(x==3)
Compute y for x==3 // That's 3
Call BunnyEars(x==2)
Compute y for x==2 // That's 2
Call BunnyEars(x==1)
Compute y for x==1
Call BunnyEars(x==0)
return 0 // Zero bunnies --> zero ears
return 2+0 --> 2
return 3+2 --> 5
return 2+5 --> 7
return 1+7 --> 8
return 2+8 --> 10
Once you see that more than one call to BunnyEars is active at the same time, this should start to make sense: the chain of calls goes on without returning until it hits the x==0 "no bunny - no ears!" clause, at which point the chain starts to unroll, adding the proper number of ears to the return value of the previous invocation.
So for BunnyEars(5) let's trace it.
BunnyEars(5)
1 + BunnyEars(4)
1 + 2 + BunnyEars(3)
1 + 2 + 3 + BunnyEars(2)
1 + 2 + 3 + 2 + BunnyEars(1)
1 + 2 + 3 + 2 + 3 + BunnyEars(0)
1 + 2 + 3 + 2 + 3 + 0
Note that none of the adding actually happens until the last BunnyEars call. Everytime it tries to add to the result of a recursive call it has to wait for the return, which will then call a new one etc. Then it works backwards returning to all of the methods adding the result along the way, before finally returning the result to the caller.
Try breaking it down case-by-case.
Say you have no bunnies
BunnyEars(0) will return 0, because it doesn't go into any of the other cases.
Say you have one bunny
BunnyEars(1) will return 3 + BunnyEars(0), which we already know is 0. So it will evaluate to 3 + 0 which equals 3.
Say you have two bunnies
BunnyEars(2) will return 2 + BunnyEars(1), which we already know is 3. So it will evaluate to 2 + 3 which equals 5.
Continue with this pattern, and it should illustrate how to step through this logic recursively.
I'll give another, easier, recursive example. Say we want the sum of all integer numbers up to n:
public static int sumUpTo(int n) {
if(n == 0) return 0;
return n + sumUpTo(n - 1);
}
Let's call this function for n equals 0. Of course, the check succeeds, and we get 0 as return value.
Let's call this function for n equals 1. The check fails, so we return 1 plus the result of sumUpTo(0). We already know this results in 0, so the final result is 1. We could say the result is 1 + sumUpTo(1 - 1) = 1 + sumUpTo(0) = 1 + 0 = 1.
For 2, we get the call: 2 + sumUpTo(2 - 1) = 2 + sumUpTo(1) = ... = 3. And so on. The accumulation you desired is done on the fly.