How does this implementation of Fibonacci(n) work? [recursion] - java

Theres an exercise from a Java book I'm reading that has me confused:
A Fibonacci sequence is the sequence of numbers 1, 1, 2, 3, 5, 8,
13, 21, 34, etc., where each number (from the third on) is the sum
of the previous two. Create a method that takes an integer as an
argument and displays that many Fibonacci numbers starting from the
beginning. If, e.g., you run java Fibonacci 5 (where Fibonacci is
the name of the class) the output will be: 1, 1, 2, 3, 5.
I could have swore that it would need an array or some way of storing the previous numbers but when I saw the answer it wasn't the case:
import java.util.*;
public class Fibonacci {
static int fib(int n) {
if (n <= 2)
return 1;
return fib(n-1) + fib(n-2);
}
public static void main(String[] args) {
// Get the max value from the command line:
int n = Integer.parseInt(args[0]);
if(n < 0) {
System.out.println("Cannot use negative numbers"); return;
}
for(int i = 1; i <= n; i++)
System.out.print(fib(i) + ", ");
}
}
Would someone be able to explain how using a function within itself produces this?

The code you gave is an example of a recursive solution. When the function is called for the first time, it executes until it calls itself. Its state is stored on the stack, and the code begins executing again with new input data. This process repeats until the input is less than 2, at which point 1 is returned, and the answer returns to the previous caller.
For example, calling fib(5) results in the following execution:
fib(5):
fib(4):
fib(3):
fib(2): 1
fib(1): 1
fib(2): 1
fib(3):
fib(2): 1
fib(1): 1
Note that you are partially correct. Intermediate results are stored on the stack in this solution. That is one of the reasons why the recursive solution is so expensive. The other is its O(2^n) complexity. However, if is possible to compute Fibonacci(n) iteratively and without storing all previous results. All you really need is to store the last to results and count from 1 up to n.

This is a recursive solution. A recursive function calls itself until a given stop condition is met. Then each call exits until only the first call remains. That first call outputs the result.
In your solution, the stop condition is :
if (n <= 2)
return 1;
until this condition is met, the function will make successive calls to itself. Each call reduces the int passed as a parameter. When it reaches 2, the stop condition dictates that the function returns with value 1 (the result of n=1 and n=2 in fibonacci(n) ).
Because the fibonacci is the sum of the last two numbers, the recursive part of the function,
return fib(n-1) + fib(n-2);
does a sum of n-1 and n-2 (as I said, the two last numbers of the sequence). When the n equals 2, these calls to function fib will finally have a value, and will be returned.
Example, if n = 3, the recursive part will call fib(2) and fib(1), both are equal or less than 2, so both calls will return 1. So the printf will print 1, 1, 2.
2 is the sum of 1 + 1 (I know it's obvious, but sometimes stating the obvious helps).

F(n)
/ \
F(n-1) F(n-2)
/ \ / \
F(n-2) F(n-3) F(n-3) F(n-4)
/ \
F(n-3) F(n-4)
Important point to note is this algorithm is exponential because it does not store the result of previous calculated numbers. eg F(n-3) is called 3 times.
For more details refer algorithm by dasgupta chapter 0.2

This is the standard example for an recursive function.
The Fibonacci Numbers are declared recursive, too.
Both fib(1) and fib(2) are declared as 1. All others are calculated by adding the last two fibonacci numbers, so fib(3)=fib(2)+fib(1).
Compare this to the calculation method which does exactly this:
static int fib(int n) {
if (n <= 2)
return 1;
return fib(n-1) + fib(n-2);
}
By the way, this is a very slow way to calculate the fibonacci numbers, using two variables (you don't need all of them for the last one, only the last two!) and a loop is in O(n), the recursive function above has O(2^n) operations.

Related

Using recursion to determine the number of digits

I'm currently stuck on one line of code that I'm not fully understanding.
So, I'm reading example codes from the book, and one of "programs" used recursion to determine the number of digits in an integer n. The one line of code that I got stuck at and do not fully understand is:
if (number >= 10) {
return numberOfDigits(number / 10) + 1;
For an example, this makes the number 42 return 2, which it's supposed to do. But how exactly does the function return 2? 42 divided by 10 is equal to 4,2 or 4. That plus 1 is 5, so how does it return 2?
Recursion is a way to get one call of the method to perform some of the work, while deferring the remainder of the work to making another recursive call. Here, a "number of digits" recursive method says that the number of digits in a number is equal to 1 for the last digit plus the number of digits remaining after the last digit is removed.
In the return statement, the + 1 counts the last digit in the number, while number / 10 performs truncating integer division to remove the last digit. The recursive call counts the digits in the number with the last digit removed.
What you haven't shown is the base case of the recursion, when the number is single-digit (not greater than or equal to 10). That is simply 1 digit. The value 4 is not figured into the calculation. The method effectively counts the digits, one at a time, until there are no more digits left. There is one recursive method call per digit.
The full method probably looks something like this:
public int numberOfDigits(int number) {
if (number >= 10) {
return numberOfDigits(number / 10) + 1;
}
// base case: only one digit
return 1;
}
By inspection, if we pass a two digit number, the if statement will be hit, which will return whatever the recursive call of the input / 10 is, plus one. Let's say the input were 42. In this case, it would return numberOfDigits(42 / 10) + 1. We know that numberOfDigits(4) returns 1, so this would return a total of 2, which is correct.
Using inductive reasoning, we can build up to convince ourselves of any number of arbitrary length.
Side note: In my travels, I have more often seen the base case handled first using an if statement, with the inductive case happening by default. So, I would have expected to see this code:
public int numberOfDigits(int number) {
if (number < 10) return 1;
return numberOfDigits(number / 10) + 1;
}

Counting all permutations of a string (Cracking the Coding Interview, Chapter VI - Example 12)

In Gayle Laakman's book "Cracking the Coding Interview", chapter VI (Big O), example 12, the problem states that given the following Java code for computing a string's permutations, it is required to compute the code's complexity
public static void permutation(String str) {
permutation(str, "");
}
public static void permutation(String str, String prefix) {
if (str.length() == 0) {
System.out.println(prefix);
} else {
for (int i = 0; i < str.length(); i++) {
String rem = str.substring(0, i) + str.substring(i + 1);
permutation(rem, prefix + str.charAt(i));
}
}
}
The book assumes that since there will be n! permutations, if we consider each of the permutations to be a leaf in the call tree, where each of the leaves is attached to a path of length n, then there will be no more that n*n! nodes in the tree (i.e.: the number of calls is no more than n*n!).
But shouldn't the number of nodes be:
since the number of calls is equivalent to the number of nodes (take a look at the figure in the video Permutations Of String | Code Tutorial by Quinston Pimenta).
If we follow this method, the number of nodes will be 1 (for the first level/root of the tree) + 3 (for the second level) + 3*2 (for the third level) + 3*2*1 (for the fourth/bottom level)
i.e.: the number of nodes = 3!/3! + 3!/2! + 3!/1! + 3!/0! = 16
However, according to the aforementioned method, the number of nodes will be 3*3! = 18
Shouldn't we count shared nodes in the tree as one node, since they express one function call?
You're right about the number of nodes. That formula gives the exact number, but the method in the book counts some multiple times.
Your sum also seems to be approach e * n! for large n, so can be simplified to O(n!).
It's still technically correct to say the number of calls is no more than n * n!, as this is a valid upper bound. Depending on how this is used, this can be fine, and may be easier prove.
For the time complexity, we need to multiply by the average work done for each node.
First, check the String concatenation. Each iteration creates 2 new Strings to pass to the next node. The length of one String increases by 1, and the length of the other decreases by 1, but the total length is always n, giving a time complexity of O(n) for each iteration.
The number of iterations varies for each level, so we can't just multiply by n. Instead look at the total number of iterations for the whole tree, and get the average for each node. With n = 3:
The 1 node in the first level iterates 3 times: 1 * 3 = 3
The 3 nodes in the second level iterate 2 times: 3 * 2 = 6
The 6 nodes in the third level iterate 1 time: 6 * 1 = 6
The total number of iterations is: 3 + 6 + 6 = 15. This is about the same as number of nodes in the tree. So the average number of iterations for each node is constant.
In total, we have O(n!) iterations that each do O(n) work giving a total time complexity of O(n * n!).
According to your video where we have string with 3 characters (ABC), the number of permutations is 6 = 3!, and 6 happens to be equal to 1 + 2 + 3. However, if we have a string with 4 characters (ABCD), the number of permutations should be 4 * 3! as D could be in any position from 1 to 4. With each position of D you can generate 3! permutations for the rest. If you re-draw the tree and count the number of permutations you will see the difference.
According to your code, we have n! = str.length()! permutations, but in each call of the permutations, you also run a loop from 0 to n-1. Therefore, you have O(n * n!).
Update in response to the edited question
Firstly, in programming, we often have either 0->n-1 or 1->n not 0->n.
Secondly, we don't count the number of nodes in this case as if you take a look at the recursion tree in the clip again, you will see nodes duplicated. The permutations in this case should be the number of leaves which are unique among each other.
For instance, if you have a string with 4 characters, the number of leaves should be 4 * 3! = 24 and it would be the number of permutations. However, in your code snippet, you also have a 0->n-1 = 0->3 loop in each permutation, so you need to count the loops in. Thus, your code complexity in this case is O(n *n!) = O(4 * 4!).

Recursive Pascal's Triangle Row big O cost

I'm studying for CS interviews and I decided to try making up my own problem and solving it recursively.
The question I am trying to solve is this: I want to be able to write a recursive function that finds the nth row of pascal's triangle.
Ex pascals(1) -> 1
pascals(2) -> 1,1
pascals(3) -> 1,2,1
I believe I have solved this function. It takes a helper function to get it started with the base case.
function int[] nthPascal(int[] a, int n){
// in the case that the row has been reached return the completed array
if(n==1){
return a;
}
// each new row of pascal's triangle is 1 element larger. Ex 1, 11, 121,1331 etc.
int[] newA = new int[a.length()+1];
//set the ends. Technically this will always be 1.
// I thought it looked cleaner to do it this way.
newA[0]=a[0];
newA[newA.length-1]=a[a.length-1];
//so I loop through the new array and add the elements to find the value.
//ex 1,1 -> -,2,- The ends of the array are already filled above
for(int i=1; i<a.length; i++){
// ex 1+1 = 2 for 1,1 -> 1,2,1
newA[i]=a[i-1]+a[i]
}
//call the recursive function if we are not at the desired level
return nthPascal(newA,n-1);
}
/**
*The helper function
*/
public int[] helperPascal(int n){
return nthPascal(int[] {1},n);
}
My question is how do I find the bigO cost?
I am familiar with common algorithm costs and how to find them. The recursion in this makes it confusing for me.
I know it's clearly not constant, n, nlogn, etc. My thought was that it was 3^n?
I searched for an example and found:
Pascal's Triangle Row Sequence
and
What is the runtime of this algorithm? (Recursive Pascal's triangle).
But they are trying to find a specific element in a given location I believe. I couldn't find anyone implementing pascal's triangle this way and talking about bigO cost.
Is this because there is a better way to write a recursive row finding pascal's function? If so please share :)
Each time you call nthPascal, it calls itself recursively just once. Therefore, you can get the time complexity by adding the time complexities of each invocation of the function (excluding the recursive call). (If you had a function that traverses a binary tree, it would typically call itself recursively twice, which makes the computation more complicated. Here, though, since it calls itself only once, the computation is pretty simple.)
Each invocation of the function has a loop that executes a.length times, and the body of the loop executes in constant time. There aren't any other loops or any other statements that execute in anything but constant time, except for when you allocate the array intA because Java will intialize every element of the array. The result, though, is that when you call nthPascal with an array of length M, the execution time will be O(M) not counting the recursive call.
So assuming that the execution time is roughly M*k for some constant k, that means the total execution time will be 1*k + 2*k + 3*k + ... + (n-1)*k. And 1 + 2 + 3 + ... + n - 1 is (n * (n - 1)) / 2, which is O(n2). So O(n2) is the answer you're looking for.
For each recursive call, you are doing a for loop of size k, where k is the depth of the recursive call (at depth k, you have an array of size k).
To get the complete row at depth n, you call nthPascal at depth 1, 2, ..., n.
Therefore, your total complexity will be 1+2+...+n=n(n+1)/2 = O(n²).

Find the sum of all even-valued terms in the Fibonacci Sequence

I'm having trouble figuring why the following code isn't producing the expected output. Instead, result = 272 which does not seem right.
/*
*Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
*Find the sum of all the even-valued terms in the sequence which do not exceed four million.
*/
public class Fibonacci
{
public static void main (String[] args)
{
int result = 0;
for(int i=2;i<=33;i++)
{
System.out.println("i:" + fib(i));
if(i % 2 == 0) //if i is even
{
result += i;
System.out.println("result:" + result);
}
}
}
public static long fib(int n)
{
if (n <= 1)
return n;
else
return fib(n-1) + fib(n-2);
}
}
The line result += i; doesn't add a Fibonacci number to result.
You should be able to figure out how to make it add a Fibonacci number to result.
Hint: Consider making a variable that stores the number you're trying to work with.
First of all, you got one thing wrong for the Fib. The definition for Fib can be found here: http://en.wikipedia.org/wiki/Fibonacci_number.
Second of all (i % 2) is true for every other number (2, 4, 6 and so), which will man that it is true for fib(2), fib(4), and so on.
And last, result += i adds the index. What you wan't to add is the result of the fib(i). So first you need to calculate fib(i), store that in a variable, and check if THAT is an even or odd number, and if it is, then add the variable to the result.
[Edit]
One last point: doing fib in recursion when you wan't to add up all the numbers can be really bad. If you are working with to high numbers you might even end up with StackOverflowException, so it is always a good idea to try and figure a way so that you don't have to calculate the same numbers over and over again. In this example, you want to sum the numbers, so instead of first trying fib(0), then fib(1) and so on, you should just go with the list, check every number on the way and then add it to the result if it matches your criteria.
Well, here's a good starting point, but it's C, not Java. Still, it might help: link text

How does the recursion here work?

Code 1:
public static int fibonacci (int n){
if (n == 0 || n == 1) {
return 1;
} else {
return fibonacci (n-1) + fibonacci (n-2);
}
}
How can you use fibonacci if you haven't gotten done explaining what it is yet? I've been able to understand using recursion in other cases like this:
Code 2:
class two
{
public static void two (int n)
{
if (n>0)
{
System.out.println (n) ;
two (n-1) ;
}
else
{
return ;
}
}
public static void main (String[] arg)
{
two (12) ;
}
}
In the case of code 2, though, n will eventually reach a point at which it doesn't satisfy n>0 and the method will stop calling itself recursively. In the case of code 2, though, I don't see how it would be able to get itself from 1 if n=1 was the starting point to 2 and 3 and 5 and so on. Also, I don't see how the line return fibonacci (n-1) + fibonacci (n-2) would work since fibonacci (n-2) has to contain in some sense fibonacci (n-1) in order to work, but it isn't there yet.
The book I'm looking at says it will work. How does it work?
Well, putting aside what a compiler actually does to your code (it's horrible, yet beautiful) and what how a CPU actually interprets your code (likewise), there's a fairly simple solution.
Consider these text instructions:
To sort numbered blocks:
pick a random block.
if it is the only block, stop.
move the blocks
with lower numbers to the left side,
higher numbers to the right.
sort the lower-numbered blocks.
sort the higher-numbered blocks.
When you get to instructions 4 and 5, you are being asked to start the whole process over again. However, this isn't a problem, because you still know how to start the process, and when it all works out in the end, you've got a bunch of sorted blocks. You could cover the instructions with slips of paper and they wouldn't be any harder to follow.
In the case of code 2 though n will eventualy reach a point at which it doesnt satisfy n>0 and the method will stop calling itself recursivly
to make it look similar you can replace condition if (n == 0 || n == 1) with if (n < 2)
Also i don't see how the line `return fibonacci (n-1) + fibonacci (n-2) would work since fibbonacci n-2 has to contain in some sense fibonacci n-1 in order to wrok but it isn't there yet.
I suspect you wanted to write: "since fibbonacci n-1 has to contain in some sense fibonacci n-2"
If I'm right, then you will see from the example below, that actually fibonacci (n-2) will be called twice for every recursion level (fibonacci(1) in the example):
1. when executing fibonacci (n-2) on the current step
2. when executing fibonacci ((n-1)-1) on the next step
(Also take a closer look at the Spike's comment)
Suppose you call fibonacci(3), then call stack for fibonacci will be like this:
(Veer provided more detailed explanation)
n=3. fibonacci(3)
n=3. fibonacci(2) // call to fibonacci(n-1)
n=2. fibonacci(1) // call to fibonacci(n-1)
n=1. returns 1
n=2. fibonacci(0) // call to fibonacci(n-2)
n=0. returns 1
n=2. add up, returns 2
n=3. fibonacci(1) //call to fibonacci(n-2)
n=1. returns 1
n=3. add up, returns 2 + 1
Note, that adding up in fibonacci(n) takes place only after all functions for smaller args return (i.e. fibonacci(n-1), fibonacci(n-2)... fibonacci(2), fibonacci(1), fibonacci(0))
To see what is going on with call stack for bigger numbers you could run this code.
public static String doIndent( int tabCount ){
String one_tab = new String(" ");
String result = new String("");
for( int i=0; i < tabCount; ++i )
result += one_tab;
return result;
}
public static int fibonacci( int n, int recursion_level )
{
String prefix = doIndent(recursion_level) + "n=" + n + ". ";
if (n == 0 || n == 1){
System.out.println( prefix + "bottommost level, returning 1" );
return 1;
}
else{
System.out.println( prefix + "left fibonacci(" + (n-1) + ")" );
int n_1 = fibonacci( n-1, recursion_level + 1 );
System.out.println( prefix + "right fibonacci(" + (n-2) + ")" );
int n_2 = fibonacci( n-2, recursion_level + 1 );
System.out.println( prefix + "returning " + (n_1 + n_2) );
return n_1 + n_2;
}
}
public static void main( String[] args )
{
fibonacci(5, 0);
}
The trick is that the first call to fibonacci() doesn't return until its calls to fibonacci() have returned.
You end up with call after call to fibonacci() on the stack, none of which return, until you get to the base case of n == 0 || n == 1. At this point the (potentially huge) stack of fibonacci() calls starts to unwind back towards the first call.
Once you get your mind around it, it's kind of beautiful, until your stack overflows.
"How can you use Fibonacci if you haven't gotten done explaining what it is yet?"
This is an interesting way to question recursion. Here's part of an answer: While you're defining Fibonacci, it hasn't been defined yet, but it has been declared. The compiler knows that there is a thing called Fibonacci, and that it will be a function of type int -> int and that it will be defined whenever the program runs.
In fact, this is how all identifiers in C programs work, not just recursive ones. The compiler determines what things have been declared, and then goes through the program pointing uses of those things to where the things actually are (gross oversimplification).
Let me walkthrough the execution considering n=3. Hope it helps.
When n=3 => if condition fails and else executes
return fibonacci (2) + fibonacci (1);
Split the statement:
Find the value of fibonacci(2)
Find the value of fibonacci(1)
// Note that it is not fib(n-2) and it is not going to require fib(n-1) for its execution. It is independent. This applies to step 1 also.
Add both values
return the summed up value
The way it gets executed(Expanding the above four steps):
Find the value of fibonacci(2)
if fails, else executes
fibonacci(1)
if executes
value '1' is returned to step 1.2. and the control goes to step 1.3.
fibonacci(0)
if executes
value '1' is returned to step 1.3. and the control goes to step 1.4.
Add both
sum=1+1=2 //from steps 1.2.2. and 1.3.2.
return sum // value '2' is returned to step 1. and the control goes to step 2
Find the value of fibonacci(1)
if executes
value '1' is returned
Add both values
sum=2+1 //from steps 1.5. and 2.2.
return the summed up value //sum=3
Try to draw an illustration yourself, you will eventually see how it works. Just be clear that when a function call is made, it will fetch its return value first. Simple.
Try debugging and use watches to know the state of the variable
Understanding recursion requires also knowing how the call stack works i.e. how functions call each other.
If the function didn't have the condition to stop if n==0 or n==1, then the function would call itself recursively forever.
It works because eventually, the function is going to petter out and return 1. at that point, the return fibonacci (n-1) + fibonacci (n-2) will also return with a value, and the call stack gets cleaned up really quickly.
I'll explain what your PC is doing when executing that piece of code with an example:
Imagine you're standing in a very big room. In the room next to this room you have massive amounts of paper, pens and tables. Now we're going to calculate fibonacci(3):
We take a table and put it somewhere in the room. On the table we place a paper and we write "n=3" on it. We then ask ourselves "hmm, is 3 equal to 0 or 1?". The answer is no, so we will do "return fibonacci (n-1) + fibonacci (n-2);".
There's a problem however, we have no idea what "fibonacci (n-1)" and "fibonacci (n-2)" actually do. Hence, we take two more tables and place them to the left and right of our original table with a paper on both of them, saying "n=2" and "n=1".
We start with the left table, and wonder "is 2 equal to 0 or 1?". Of course, the answer is no, so we will once again place two tables next to this table, with "n=1" and "n=0" on them.
Still following? This is what the room looks like:
n=1
n=2 n=3 n=1
n=0
We start with the table with "n=1", and hey, 1 is equal to 1, so we can actually return something useful! We write "1" on another paper and go back to the table with "n=2" on it. We place the paper on the table and go to the other table, because we still don't know what we're going to do with that other table.
"n=0" of course returns 1 as well, so we write that on a paper, go back to the n=2 table and put the paper there. At this point, there are two papers on this table with the return values of the tables with "n=1" and "n=0" on them, so we can compute that the result of this method call is actually 2, so we write it on a paper and put it on the table with "n=3" on it.
We then go to the table with "n=1" on it all the way to the right, and we can immediately write 1 on a paper and put it back on the table with "n=3" on it. After that, we finally have enough information to say that fibonacci(3) returns 3.
It's important to know that the code you are writing is nothing more than a recipe. All the compiler does is transform that recipe in another recipe your PC can understand. If the code is completely bogus, like this:
public static int NotUseful()
{
return NotUseful();
}
will simply loop endlessly, or as in my example, you'll keep on placing more and more tables without actually getting anywhere useful. Your compiler doesn't care what fibonacci(n-1) or fibonacci(n-2) actually do.

Categories