How to read recursion methods accurately - java

I'm preparing for a java programming exam that's coming up in a few days and I've been tryna get my head around this:
The initial starting value of int num is 8
public int func1(int num)
{
if(num <=1) return 1;
return num + func1 (num - 3);
}
How do you go through through the return num + func1 (num - 3) part?
I don't get how that line of code works

I hope this will help you understand recursion.
return 8 + func1(5)
return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
and finally returns like
return 8 + 5 + 3
return 8 + 8
return 16

Easiest way to understand recursion is
Assume that the whole public int func1(int num) is inserted in the return
so ur function returns somewhat in this way
return 8 + func1((8) - 3) // i.e return 8 + func1(5)
return 8 + 5 + func1((5) - 3) // i.e return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1((2) - 3) // i.e return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
So total will be 16

Just trace through it the exact same as for any other method call. It's just calling itself which is another way to do a loop.
i.e.
func1(8)
calls func1(8-3)
calls func1(5-3)
calls func1(2-3)
returns 1 as -1 < 1
returns 2+1
returns 5+3
returns 8+8
So the final result is 16.

"The only way to understand recursion is to understand recursion".
Now seriously, you need to think of the execution of a recursive program as a stack with a basic case and a general case:
For instance the factorial method:
Basic case: f(n) = 1, if n = 0.
General case: f(n) = n*f(n-1), otherwise.
Result would be:
f(n) = n*f(n-1)
f(n-1) = (n-1)*f(n-2)
...
f(2) = 2*f(1)
f(1) = 1*f(0)
f(0) = 1
Basically you need to go down until the basic case and then reconstruc the result via the partial results you are finding.
Recursive algorithms are very useful for some methods which otherwise would require lots of memory to store intermediates value.

Related

Java simple recursion explanation

I was implementing a very simple recursive method to multiply two numbers together. I am very a hard time understanding the basics of recursion.
Is anyone able to explain to me (Line-by-line if possible) how this code works? I am especially confused about the base case is written to return 0 when in reality the actual multiplication is returned instead.
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n; //Recursive Case - Decrements m, while adding n
}
Thanks for any help
I will try to make this answer beginner friendly. First I will answer this part of your question:
I am especially confused about the base case is written to return 0
when in reality the actual multiplication is returned instead.
The value returned in the base case depends on how you are implementing your algorithm. Here in order to calculate n*m, we extend this multiplication to addition. A few examples will make this more clear.
2*3 = 2 + 2 + 2 + 0
4*1 = 4 + 0
5*5 = 5 + 5 + 5 + 5 + 5 + 0
n*m = n + n + n + ... + (m times) + 0
That is why we return 0 in the base case, we have to stop the recursion without making any change in the result and that is only possible if we add 0.
Here is the working of this program:
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n;
Let us take n = 4 and m = 3.
Our first call to the method is multiply(4, 3). We then proceed further, the base condition is false so we skip that.
We then get to this part: return multiply(n, m - 1) + n. We make another call to the same function. multiple(4, 2). Again we skip the base case. Here is a table:
multiply(4, 3) -> return multiply (4, 2) + 4
multiple(4, 2) -> return multiply (4, 1) + 4
multiple(4, 1) -> return multiply (4, 0) + 4
multiple(4, 0) -> 0
On substituting the returned values we get,
multiple(4, 3) -> return 0 + 4 + 4 + 4
multiple(4, 2) -> return 0 + 4 + 4
multiple(4, 1) -> return 0 + 4
multiple(4, 0) -> return 0
If our first call is multiply(n, m), then the end returned value is:
multiply (n, m) -> return 0 + n + n + n + ... + (m times)
I hope I have helped you. Try to construct a similar relation like this on your own and you will understand it better. Here is a link on further explanation on recursion:
https://www.geeksforgeeks.org/recursion

Total of all numbers from 1 to N will always be zero

The problem is I have to print all combinations of a sequence of
numbers from 1 to N that will always result to zero. It is allowed
to insert "+" (for adding) and "-" (for subtracting) between each
numbers so that the result will be zero.
//Output
N = 7
1 + 2 - 3 + 4 - 5 - 6 + 7 = 0
1 + 2 - 3 - 4 + 5 + 6 - 7 = 0
1 - 2 + 3 + 4 - 5 + 6 - 7 = 0
1 - 2 - 3 - 4 - 5 + 6 + 7 = 0
So how can I implement this? I am not asking for the actual
codes to do this, just a hint and ideas to solve this will
do. Thank you..
You could also use recursion here. Just remember your current integer, your max integer, your current sum and some kind of history of operations (could also be your final sequence).
In every level you proceed the path in two dirdctions: adding to your sum and substracting from it.
I did a quick implementation in Python, but it should be easy to transfer this to Java or whatever you are using.
def zero_sum(curr, n, seq, sum):
if curr == n and sum == 0:
print(seq)
elif curr < n:
zero_sum(curr + 1, n, seq + " - " + str(curr + 1), sum - (curr + 1))
zero_sum(curr + 1, n, seq + " + " + str(curr + 1), sum + (curr + 1))
zero_sum(1, 7, "1", 1)
Hopefully you get the idea.
The first step is to turn the problem into an entirely regularly formed problem:
n
∑ ±i = -1
i=2
n-2
∑ ±(i+2) = -1
i=0
The term 1 at the start has no prefix +/-. And the walking index better runs from 0 when using a Java array.
So one has n-1 coefficients -1 or +1 for the possible values.
A brute force approach would be to start with the highest values, i = n-2.
The upper/lower bounds for j = 0, ..., i would be ± (i + 1) * (2 + i + 2) / 2, so one can cut the evaluation there - when the till then calculated sum can no longer reach -1.
To represent the coefficients, one could make a new int[n - 1] or simply a new BitSet(n-1).
public void solve(int n) {
int i = n-2;
int sumDone = 0;
BigSet negates = new BitSet(n - 1);
solveRecursively(i, sumDone, negates);
}
private void solveRecursively(int i, int SumDone, BitSet negates) {
if (i < 0) {
if (sumDone == -1) {
System.out.println("Found: " + negates);
}
return;
}
...
}
The interesting, actual (home) work I leave to you. (With BitSet better i = n, ... , 2 by -1 seems simpler though.)
The question here is how much efficiency matters. If you're content to do a brute-force approach, a regression method like the one indicated by holidayfun is a fine way to go, though this will become unwieldy as n gets large.
If performance speed matters, it may be worth doing a bit of math first. The easiest and most rewarding check is whether such a sum is even possible: since the sum of the first n natural numbers is n(n+1)/2, and since you want to divide this into two groups (a "positive" group and a "negative" group) of equal size, you must have that n(n+1)/4 is an integer. Therefore if neither n nor n+1 is divisible by four, stop. You cannot find such a sequence that adds to zero.
This and a few other math tricks might speed up your application significantly, if speed is of the essence. For instance, finding one solution will often help you find others, for large n. For instance, if n=11, then {-11, -10, -7, -5} is one solution. But we could swap the -5 for any combination that adds to 5 that isn't in our set. Thus {-11, -10, -7, -3, -2} is also a solution, and similarly for -7, giving {-11, -10, -5, -4, -3} as a solution (we are not allowed to use -1 because the 1 must be positive). We could continue replacing the -10, the -11, and their components similarly to pick up six more solutions.
This is probably how I'd approach this problem. Use a greedy algorithm to find the "largest" solution (the solution using the largest possible numbers), then keep splitting the components of that solution into successively smaller solutions. It is again fundamentally a recursion problem, but one whose running time decreases with the size of the component under consideration and which at each step generates another solution if a "smaller" solution exists. That being said, if you want every solution then you still have to check non-greedy combinations of your split (otherwise you'd miss solutions like {-7, -4, -3} in your n=7 example). If you only wanted a lot of solutions it would definitely be faster; but to get all of them it may be no better than a brute-force approach.
If I were you I would go for a graph implementation, and DFS algorithm. Imagine you have N nodes that are representing your numbers. Each number is connected to another via an "add" edge, or a "subtract" edge. So you have a fully connected graph. You can start from a node and compute all dfs paths that lead to zero.
For more information about DFS algorithm, you can see the wikipage.
Edit: In order to clarify my solution, the graph you will end up having will be a multigraph, which means that it has more than one edge between nodes. DFS in a multigraph is slightly more complicated, but it is not that hard.
I would suggest a straight forward solution because as you mentioned you are dealing with consecutive integer from 1 to N which are fixed. The only things that vary are the operators in between.
Let's look at your example before we implement a general solution:
For n = 7 you need somehow to produce all possible combinations:
1+2+3+4+5+6+7
1+2+3+4+5+6-7
1+2+3+4+5-6+7
1+2+3+4+5-6-7
...
1-2-3-4-5-6+7
1-2-3-4-5-6-7
If we remove the numbers from above strings/expressions then we'll have:
++++++
+++++-
++++-+
++++--
...
----+-
-----+
------
Which reminds on binary numbers; if we interpret + as 0 and - as 1 the above can be mapped to the binary numbers from 000000 to 111111.
For an input n you'll have n-1 operators inbetween, which means the count of all possible combinations will be 2^n-1.
Putting all the above together something like below can be used to print those which sums are zero:
public static void main(String args[]) throws IOException{
permute(7);
}
public static void permute(int n){
int combinations = (int)Math.pow(2, n-1);
for(int i = 0; i < combinations; i++){
String operators =String.format("%"+(n-1)+"s", Integer.toBinaryString(i)).replace(' ', '0');
int totalSum = 1;
StringBuilder sb = new StringBuilder();
for(int x = 0; x< operators.length(); x++){
sb.append(x+1);
if(operators.charAt(x)=='0'){
sb.append("+");
totalSum = totalSum + (x+2);
}
else{
sb.append("-");
totalSum = totalSum-(x+2);
}
}
sb.append(n);
if(totalSum == 0){
System.out.println(sb.toString() + " = " + totalSum);
}
}
}
Note/Example: String.format("%6s", Integer.toBinaryString(13)).replace(' ', '0') will produce a string with length = 6 from the binary representation of 13 with leading zeros, i.e 001101 instead of 1101 so that we get the required length of the operators.
This is an interesting question. It involves more math than programming because only if you discover the math portion then you may implement an efficient algorithm.
However even before getting into the math we must actually understand what exactly the question is. The question can be rephrased as
Given array [1..n], find all possible two groups (2 subarrays) with equal sum.
So the rules;
sum of [1..n] is n*n(+1)/2
If n*(n+1)/2 is odd then there is no solution.
If your target sum is t then you should not iterate further for lower values than Math.ceil((Math.sqrt(8*t+1)-1)/2) (by solving n from n(n+1)/2 = t equation)
Sorry... I know the question requests Java code but I am not fluent in Java so the code below is in JavaScript. It's good though we can see the results. Also please feel free to edit my answer to include a Java version if you would like to transpile.
So here is the code;
function s2z(n){
function group(t,n){ // (t)arget (n)umber
var e = Math.ceil((Math.sqrt(8*t+1)-1)/2), // don't try after (e)nd
r = [], // (r)esult
d; // (d)ifference
while (n >= e){
d = t-n;
r = d ? r.concat(group(d, d < n ? d : n-1).map(s => s.concat(n)))
: [[n]];
n--;
}
return r;
}
var sum = n*(n+1)/2; // get the sum of series [1..n]
return sum & 1 ? "No solution..!" // if target is odd then no solution
: group(sum/2,n);
}
console.log(JSON.stringify(s2z(7)));
So the result should be [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]].
what does this mean..? If you look into that carefuly you will notice that
These are all the possible groups summing up to 14 (half of 28 which is the sum of [1..7].
The first group (at index 0) is complemented by the last group (at index length-1) The second is complemented with the second last and so on...
Now that we have the interim results it's up to us how to display them. This is a secondary and trivial concern. My choice is a simple one as follows.
var arr = [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]],
res = arr.reduce((r,s,i,a) => r+s.join("+")+"-"+a[a.length-1-i].join("-")+" = 0 \n","");
console.log(res);
Of course you may put the numbers in an order or might stop halfway preventing the second complements taking positive values while the firsts taking negative values.
This algorithm is not hard tested and i might have overlooked some edges but I believe that this should be a very efficient algorithm. I have calculated up to [1..28] in a very reasonable time resulting 2399784 uniques groups to be paired. The memory is only allocated for the constructed result set despite this is a resursive approach.
It is a good question, but first you must have to try to solve it and show us what you tried so we can help you in the solution, this way you will improve more effectively.
However, the below code is a solution I have write before years, I think the code need improvement but it will help..
public static void main(String[] args) {
String plus = " + ", minus = " - ";
Set<String> operations = new HashSet<>();
operations.add("1" + plus);
operations.add("1" + minus);
// n >= 3
int n = 7;
for (int i = 1; i < n - 1; i++) {
Set<String> newOperation = new HashSet<>();
for (String opt : operations) {
if ((i + 2) == n) {
newOperation.add(opt + (i + 1) + plus + n);
newOperation.add(opt + (i + 1) + minus + n);
} else {
newOperation.add(opt + (i + 1) + plus);
newOperation.add(opt + (i + 1) + minus);
}
}
operations.clear();
operations.addAll(newOperation);
}
evalOperations(operations);
}
private static void evalOperations(Set<String> operations) {
// from JDK1.6, you can use the built-in Javascript engine.
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
for (String opt : operations) {
if ((int) engine.eval(opt) == 0) {
System.out.println(opt + " = 0");
}
}
} catch (ScriptException e) {
e.printStackTrace();
}
}
First, the question is the special case of sum to N.
Second, sum a list to N, could be devided to the first element plus sublist and minus sublist.
Third, if there are only one element in the list, check if n equals the element.
Fourth, make recursion.
Here's the scala implementation, try finishing your java version:
def nSum(nums: List[Int], n: Int, seq: String, res: ListBuffer[String]): Unit =
nums match {
case Nil => if (n == 0) res.append(seq)
case head :: tail => {
nSum(tail, n - head, seq + s" + $head", res)
nSum(tail, n + head, seq + s" - $head", res)
}
}
def zeroSum(nums: List[Int]): List[String] = {
val res = ListBuffer[String]()
nSum(nums.tail, -nums.head, s"${nums.head}", res)
res.map(_ + " = 0").toList
}
val expected = List(
"1 + 2 - 3 + 4 - 5 - 6 + 7 = 0",
"1 + 2 - 3 - 4 + 5 + 6 - 7 = 0",
"1 - 2 + 3 + 4 - 5 + 6 - 7 = 0",
"1 - 2 - 3 - 4 - 5 + 6 + 7 = 0")
assert(expected == zeroSum((1 to 7).toList))

Java Order of Operation

I am having some problems understanding stacks and order of operations in java. If I had the following:
operation(7, 2)
public int operation(int x, int y) {
if (x == y)
return 0;
else
return operation(x – 1, y) + 2;
}
What would be the result? I am being told that it should be a single number result but I don't understand how (x – 1, y) + 2 can be single number. I have gotten it to:
(x – 1, y) + 2
(7 - 2, 2) + 2
(5, 2) + 2
But I don't understand the method for adding the 2 at the end. Wouldn't this need to return both values separated by a comma?
Wouldn't this need to return both values separated by a comma?
Nope.
operation(x – 1, y) + 2 is a recursive function.
operation(7 - 1, 2) + 2 => operation(6, 2) + 2 This calls the operation function with arguments 6 and 2 (similar to how you did the initial call). This call will eventually end up with a number to which 2 is added and returned.
Taking a smaller number for better visualization operation(4, 2)
operation(4, 2) -> return operation(3, 2) + 2
operation(3, 2) -> return operation(2, 2) + 2
operation(2, 2) -> return 0 (the base case)
.. stack unwinds
operation(3, 2) -> return 0 + 2
operation(4, 2) -> return 2 + 2
operatation(7, 2) returns -> 8 + 2 = 10
operatation(6, 2) returns -> 6 + 2 = 8
operatation(5, 2) returns -> 4 + 2 = 6
operatation(4, 2) returns -> 2 + 2 = 4
operatation(3, 2) returns -> 0 + 2 = 2
operatation(2, 2) returns -> 0
The recursive calls will be made till the x and y values equal, in that case operation returns 0. The return value is then added to 2 and returned to caller i.e. 0 + 2 = 2 and so on, till the first caller is returned. Hence the answer is 10.
This ends up being roughly equivalent to a for loop, actually. This code has the exact same result as operation(7, 2):
int equivOfOperation = 0;
for (int i = 2; i < 7; i++)
{
equivOfOperation += 2;
}
The recursive function will end up doing the equivalent of
for (int i = y; i < x; i++)
assuming, of course, that y < x. (In this case, operation would end up with infinite recursion).
Since several of the other answers have already shown the trace of the recursion, I won't repeat that here, but you might want to walk through their traces and convince yourself of this having the same effect as a for loop.

Tracing through a recursive function [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
For the following code segment, I am having trouble tracing through it (which I need to be able to do for my upcoming test.
public int question(int x, int y)
{
if (x ==y)
return 0;
else
return question(x-1, y) + 1;
}
I am also confused as to what the + 1 is doing. What is 1 being added on to. I know the result is five, but I need to be able to better understand the concept. Thanks for your help.
Basically:
question(8,3) will return question(7,3) + 1
question(7,3) will return question(6,3) + 1
question(6,3) will return question(5,3) + 1
question(5,3) will return question(4,3) + 1
question(4,3) will return question(3,3) + 1
and question(3,3) is 0.
It should be obvious that the result of question(8,3) is 5 by simple substitution. It should be noted that if x < y then you might get a stack overflow as x keeps decrementing and will possibly never get to x == y.
the 1 is being added onto the return from the function every time the function recurses 1 is added onto the return of int
public int question(int x, int y)
{
if (x ==y)
return 0;
else
return question(x-1, y) + 1;
}
say you call
int result = question(5,0);
since your general case calls
return question(x-1, y) + 1;
the + 1 is going to recurse until you hit the base case of
if (x ==y)
return 0;
giving you +1 +1 +1 +1 +1 +0
until x = 0 and y = 0
You can always add a couple prints to the method to better understand what it is doing:
static int question(int x, int y) {
if (x ==y) {
System.out.println(x + " == " + y);
System.out.println("return 0");
return 0;
} else {
System.out.println(x + " != " + y);
System.out.println("call question(" + (x - 1) + ", " + y + ")");
int result = question(x - 1, y);
System.out.println("return " + result + " + 1");
return result + 1;
}
}
Then call it. For example:
public static void main(String... args) {
System.out.println(question(8, 3));
}
Output:
8 != 3
call question(7, 3)
7 != 3
call question(6, 3)
6 != 3
call question(5, 3)
5 != 3
call question(4, 3)
4 != 3
call question(3, 3)
3 == 3
return 0
return 0 + 1
return 1 + 1
return 2 + 1
return 3 + 1
return 4 + 1
5
In order to understand recursion, try to write function in a mathematical way. I will first demonstrate this with the classic factorial, then explain you the example you gave.
Let fact(n) be n!. The recursive definition of factorial is:
fact(n) = 1, if n <= 1
fact(n) = n * fact(n - 1)
Note that we have 2 cases: a base case, which is a simple case that can be calculated directly, and a step case, which requires the value of a recursive call. Note that in order for the recursion to work, the recursive function call should be simpler, in order to move towards the step case. This can be implemented easily in Java:
public int factorial(int n)
{
if (n < 2)
return 1;
else
return n*factorial(n-1);
}
Returning to your function, you have to do the same process backwards. We can easily identify the 2 base cases as the branches of if:
Base case: question(x, y) = 0, if x = y
Step case: question(x, y) = question(x - 1, y) + 1, otherwise
It can be noticed that at each recursive call you subtract 1 from x and add 1 to the result. Let's unroll the recursion for question(8, 3):
question(8, 3) = question(7, 3) + 1 // You are in the step case
question(7, 3) = question(6, 3) + 1
question(6, 3) = question(5, 3) + 1
question(5, 3) = question(4, 3) + 1
question(4, 3) = question(3, 3) + 1
question(3, 3) = 0 // The base case
Now, if you replace the value of question(3, 3) in the value of question(4, 3) and do the same upwards, you find out that the result is 8.
There is no straight way to do this, but you can notice that the first parameter is decreasing by 1 and each time this is done, the result increases by 1, until the parameters are equal. Using some intuition, you may notice that this basically computes x - y.
Note that this method requires x >= y, otherwise it will crash.

How did this get 8?

Here's the code:
class qual
{
public static int fibonacci(int n)
{
if (n == 0 || n == 1)
{
return 1;
}
else
{
return fibonacci(n-1) + fibonacci(n-2);
}
}
public static void main(String[] arg)
{
System.out.println(fibonacci(5));
}
}
The output was 8.
The output should be 8 but when I look at this I think it should be 7 ((5-1) +(5-2)).
Why was the output 8? I think the reasoning behind getting 8 will make recursion maybe stop being confusing for me.
Let's treat this like algebra, I'll write f(n) instead of fibonacci(n) to save space:
f(5) = f(4) + f(3)
f(5) = f(3) + f(2) + f(2) + f(1)
f(5) = f(2) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = f(1) + f(0) + f(1) + f(1) + f(0) + f(1) + f(0) + f(1)
f(5) = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
Because it's a recursive call, so each call where the argument is not 0 or 1 calls it again.
fibonacci(7)
-> fibonacci(6) // recursively calls itself with (7-1)
-> fibonacci(5) // recursively calls itself with (6-1)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(4) // recursively calls itself with (6-2)
...
-> fibonacci(5) // recursively calls itself with (7-2)
-> fibonacci(4) // recursively calls itself with (5-1)
-> fibonacci(3) // recursively calls itself with (4-1)
-> fibonacci(2) // recursively calls itself with (3-1)
-> fibonacci(1) // recursively calls itself with (2-1)
-> fibonacci(3) // recursively calls itself with (5-2)
...
and so on.
Think about the logic like this, and you should be able to work out what it actually returns to the initial caller.
It's returning fibonacci(n-1), not n-1. When you call this with 5, you get:
return fib(4) + fib(3);
fib(4) returns:
return fib(3) + fib(2);
fib(3) returns:
return fib(2) + fib(1);
fib(2) returns:
return fib(1) + fib(0);
As soon as you reach fib(1) or fib(0), you return 1;
Working backwards, fib(2) returns 2:
return 1 /*fib(1)*/ + 1 /*fib(0)*/;
By the same logic, fib(3) returns 2 + 1, or 3. Fib(4) returns 3 + 2, or 5. Fib(5) therefor returns 5 + 3, which is your 8.
Perhaps this illustration adapted from the Structure and Interpretation of Computer Programs (SICP, or the Wizard book) will help:
Going off on a tangent, SICP is a fantastically deep though at times difficult introduction to programming. Since it uses Lisp (rather, Scheme) as its teaching language, recursion is used throughout. Even iterative processes in Lisp are based on recursive calls:
(define (factorial n)
(define (fact-iter n product)
(if (> n 1)
(fact-iter (- n 1) (* product n))
product
) )
(fact-iter n 1)
)
(factorial 5)
; returns 120
is actually iterative. Notes: car returns the head of a list, while cdr returns the tail. Operators use prefix notation; (- a b) is "a - b", (* a b) is "a * b".
Here's what your Fibonacci program looks like in Scheme:
(define (fibonacci n)
(if (or (= n 1) (= n 2))
1
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))
)
It's not ((5-1) + (5-2)), but rather (finonacci(5-1) + fibonacci(5-2))
And finonacci(5-1) reduces to fibonacci(4), which becomes (finonacci(4-1) + fibonacci(4-2)), etc.
return fibonacci (n-1) + fibonacci (n-2);
That's actually not just doing (n-1) + (n-2), it's recursively calling the fibonnacci function again.
So it's doing fibonacci (4) + fibonacci (3). That fib(4) is then evaluated to be fib(3) + fib(2), so it ends up returning fib (3) + fib (2) + fib (3). Again, each of those fib(3)'s are actually fib (2) + fib (1), and so on. It keeps breaking down like that, until it hits
if (n == 0 || n == 1)
so it ends up being a bunch of fib (1) + fib (0) + fib (1)..., which is 1 + 1 + 1..., which will end up as 8 if you actually break it all the way down.
I haven't seen this approach yet. Imagine you are storing results and building it up, where f[i] is the result of calling fibonacci(i). 0 and 1 are base cases, and the rest build on it:
f[0] = 1
f[1] = 1
f[2] = f[1] + f[0] = 1 + 1 = 2
f[3] = f[2] + f[1] = 2 + 1 = 3
f[4] = f[3] + f[2] = 3 + 2 = 5
f[5] = f[4] + f[3] = 5 + 3 = 8
The result of the function is not (5 - 1) + (5 - 2), but fibonacci( 5 - 1 ) + fibonacci( 5 - 2 ) or fibonacci( 4 ) + fibonacci( 3 ), which is 5 + 3. The sequence is:
1 1 2 3 5 8
0 1 2 3 4 5
Recursion is actually closely related to the mathematical concept of proof by induction -- and in fact the Fibonacci sequence is recursively defined, so on some level you have to already think in recursive terms to understand how it works.
To better understand the code, you can apply a beta reduction -- that is, replace each function call with the body of the function itself.
If fibonacci(n) translates to fibonacci(n - 1) + fibonacci(n - 2) then:
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(5) = (fibonacci(3) + fibonacci(2)) + (fibonacci(2) + fibonacci(1))
It's easy to see that this would go on forever, unless we made a special case. Here, we know that fibonacci(1) translates to 1, and fibonacci(0) also translates to 1. So we keep beta-reducing until all we have left are ones, which looks like:
fibonacci(5) = ((1 + 1) + (1 + (1 + 1))) + ((1 + 1) + 1)
Therefore:
fibonacci(5) = 8
The first fibonacci number are 1,1,2,3,5,8,... any other numbers would be unexpected.

Categories

Resources