Clarification on tail recursive methods - java

Is the following method tail-recursive?
I believe that it is not tail recursive because it relies on the previous results and so needs a stack frame, am I correct to state this?
public int[] fib(int n)
{
if(n <= 1){
return (new int[]{n,0});
}
else{
int[] F = fib(n-1);
return (new int[]{F[0]+ F[1], F[0]});
}
}

You are correct: It is not tail recursive because the last line is not of the form
return funcName(args);

Yes, you are correct, since it does not end with a call to itself of the form of
return fib(somevalue);
To convert it into a tail-recursive version you could do something like
// Tail Recursive
// Fibonacci implementation
class GFG
{
// A tail recursive function to
// calculate n th fibonacci number
static int fib(int n, int a, int b )
{
if (n == 0)
return a;
if (n == 1)
return b;
return fib(n - 1, b, a + b);
}
public static void main (String[] args)
{
int n = 9;
System.out.println("fib(" + n +") = "+
fib(n,0,1) );
}
}
Code taken from https://www.geeksforgeeks.org/tail-recursion-fibonacci/

Related

Is this a recursion or not?

I have an argument with my friend because I don't think fib_2() is recursion, but he says it is because it calls itself.
I don't think it is because one fib_2() doesn't have a return result for use as an argument for another fib_2().
I think fib_2() is the same with fib_3(),it's a iteration,not a recursion.
So is it a recursion or not ?
public class Demo {
public static void main(String[] args) {
System.out.printf("fib_1 -> %d\n", fib_1(10));
System.out.printf("fib_2 -> %d\n", fff(10));
System.out.printf("fib_3 -> %d\n", fib_3(10));
}
//This is recursion
public static int fib_1(int n) {
if (n == 1 || n == 2)
return 1;
return fib_1(n - 1) + fib_1(n - 2);
}
//Is this recursion or not ?
public static int fff(int n) {
int a = 1, b = 1, c = 0, count = 2;
return fib_2(a, b, n, c, count);
}
public static int fib_2(int a, int b, int n, int c, int count) {
if (count == n) {
return c;
}
int tmp = b;
b = a + b;
a = tmp;
c = b;
++count;
return fib_2(a, b, n, c, count);
}
public static int fib_3(int n) {
int a = 1, b = 1;
for (int i = 2; i < n; i++) {
int temp = b;
b = a + b;
a = temp;
}
return b;
}
}
fff is not recursive, because it does not calls itself. It calls fib_2 which has a recursive implementation, but it is not enough to make the fff method recursive.
fib_2, on the other hand, is textbook-recursive: it has a base case for count == n, and it has a recursive branch that calls fib_2 with new values of a, b, and c.
fib_2 is recursive. fff is not.
The first call of fib_2 uses returns (hence 'uses') the result of the second call.
Or formal:
Recursion is defined by two properties:
A simple base case (or cases)—a terminating scenario that does not use recursion to produce an answer
A set of rules that reduce all other cases toward the base case
Your if inside fib_2 fulfills the first property.
The call to fib_2 fulfills the second.
fib_3 is an iterative.
fib_2 is not equal to fib_3!
Two functions are equal (in a mathematical manner), if and only if they produce the same output for every given input! fib_2 and fib_3 have different parameters so this can't be true.
fib_3 may be equal to fff and/or fib_1
For equality in a computer science manner you have to consider things like side effects.
public static int fib_2(int a, int b, int n, int c, int count) {
if (count == n) {
return c;
}
int tmp = b;
b = a + b;
a = tmp;
c = b;
++count;
return fib_2(a, b, n, c, count);
}
I think in this code recussion is happening.

java fibonacci of ANY first two numbers

I need to write java methods to compute the Fibonacci series of ANY first two numbers imputed by the user, let's say that the user inputs 10 and 20, and wants the first 5 numbers of the series, the output would be 10 20 30 50 80. I have already implemented an iterative method that does this, but my trouble is with the RECURSIVE method to accomplish it.
public int fRec(int n)
{
//base case of recursion
if ((n == 0) || (n == 1))
return n;
else
//recursive step
return fRec(n-1) + fRec(n-2);
}
This is the typical recursive method to the fibonacci series, the n parameter represents up to what number the user wants the series to run, but how can i modify it to to make sure that the series uses the first two numbers that the user wants the series to begin with?
I would use memoization with a Map<Integer,Long> and pass the first and second terms to the constructor. For example,
public class Fibonacci {
public Fibonacci(long first, long second) {
memo.put(0, first);
memo.put(1, second);
}
Map<Integer, Long> memo = new HashMap<>();
public long fRec(int n) {
if (n < 0) {
return -1;
}
if (memo.containsKey(n)) {
return memo.get(n);
}
long r = fRec(n - 2) + fRec(n - 1);
memo.put(n, r);
return r;
}
public static void main(String[] args) {
Fibonacci f = new Fibonacci(10, 20);
for (int i = 0; i < 5; i++) {
System.out.println(f.fRec(i));
}
}
}
Which outputs (as requested)
10
20
30
50
80
To start with specific numbers in the series they will need to be returned for 0 and 1:
public int fib(int n, int start1, int start2) {
switch (n) {
case 0: return start1;
case 1: return start2;
default: return fib(n-1, start1, start2) + fib(n-2, start1, start2);
}
}
This is a pretty laborious way to calculate several members of the series as it's going all the way back to the start each time. Better would be to encapsulate in a class:
class Fib {
private int previous;
private int current;
public Fib(int start1, int start2) {
this.previous = start1;
this.current = start2;
}
public int next() {
int temp = previous + current;
previous = current;
current = successor;
return current;
}
}
This is another way of calculating Fibonacci series of any first two numbers.
public class StackOverflow {
public static void main(String[] args) {
int first = 10, second = 20;
System.out.println(first);
System.out.println(second);
recursive(first, second, 2);
}
public static void recursive(int first, int second, int count) {
if (count != 5){
int temp = first+second;
first= second;
second = temp;
System.out.println(second);
recursive(first, second, ++count);
}
}
}

Prime factors using recursion in Java

I'm having trouble with recursion in java. So I have the following method and i should transform it only with recursion without any loop.
public static List<Integer> primesLoop(int n) {
List<Integer> factors = new ArrayList<Integer>();
int f = 2;
while (f <= n)
if (n % f == 0) {
factors.add(f);
n /= f;
} else
f++;
return factors;
}
The recursive method should start with the same form:
public static List<Integer> primesRec(int n);
and also I should define help methods for the transformation
The result is for example:
primesRec(900) -> prime factors of 900 : [2, 2, 3, 3, 5, 5]
You can often use simple transforms from the looping form to the recursive form. Local variables must generally be moved into a parameter. There is often two forms, one providing the user interface and another, often private, that actually performs the recursive function.
public static List<Integer> primesLoop(int n) {
List<Integer> factors = new ArrayList<Integer>();
int f = 2;
while (f <= n) {
if (n % f == 0) {
factors.add(f);
n /= f;
} else {
f++;
}
}
return factors;
}
public static List<Integer> primesRecursive(int n) {
// The creation of factors and the start at 2 happen here.
return primesRecursive(new ArrayList<>(), n, 2);
}
private static List<Integer> primesRecursive(ArrayList<Integer> factors, int n, int f) {
// The while becomes an if
if (f <= n) {
// This logic could be tuned but I've left it as-is to show it still holds.
if (n % f == 0) {
factors.add(f);
// Make sure either n ...
n /= f;
} else {
// ... or f changes to ensure no infinite recursion.
f++;
}
// And we tail-recurse.
primesRecursive(factors, n, f);
}
return factors;
}
public void test() {
for (int n = 10; n < 100; n++) {
List<Integer> loop = primesLoop(n);
List<Integer> recursive = primesRecursive(n);
System.out.println("Loop : " + loop);
System.out.println("Recursive: " + recursive);
}
}
Notice the similarity between the two methods.
You can add f as an argument by overloading, and adding private method that does take it, and is invoked from the "main" public method.
In the private method, you have 3 cases:
stop clause: n==1: create a new empty list
n%f == 0: recurse with n'=n/f, f'=f, and add f to the list.
n%f != 0: recurse with n'=n, f'=f+1, don't add anything to the list.
Code:
public static List<Integer> primesRecursive(int n) {
return primesRecursive(n, 2);
}
//overload a private method that also takes f as argument:
private static List<Integer> primesRecursive(int n, int f) {
if (n == 1) return new ArrayList<Integer>();
if (n % f == 0) {
List<Integer> factors = primesRecursive(n/f, f);
factors.add(f);
return factors;
} else
return primesRecursive(n, f+1);
}
As expected, invoking:
public static void main(String args[]) {
System.out.println(primesRecursive(900));
}
Will yield:
[5, 5, 3, 3, 2, 2]
Note: If you want the factors in ascending order:
switch ArrayList implementation to LinkedList in stop clause (for performance issues)
add items with factors.add(0, f); instead factors.add(f)

Storing values of a Fibonacci sequence w/ recursion with minimal runtime

I know my code has a lot of issues right now, but I just want to get the ideas correct before trying anything. I need to have a method which accepts an integer n that returns the nth number in the Fibonacci sequence. While solving it normally with recursion, I have to minimize runtime so when it gets something like the 45th integer, it will still run fairly quickly. Also, I can't use class constants and globals.
The normal way w/ recursion.
public static int fibonacci(int n) {
if (n <= 2) { // to indicate the first two elems in the sequence
return 1;
} else { // goes back to very first integer to calculate (n-1) and (n+1) for (n)
return fibonacci(n-1) + fibonacci(n-2);
}
}
I believe the issue is that there is a lot of redundancy in this process. I figure that I can create a List to calculate up to nth elements so it only run through once before i return the nth element. However, I am having trouble seeing how to use recursion in that case though.
If I am understanding it correctly, the standard recursive method is slow because there are a lot of repeats:
fib(6) = fib(5) + fib(4)
fib(5) = fib(4) + fib(3)
fib(4) = fib(3) + 1
fib(3) = 1 + 1
Is this the correct way of approaching this? Is it needed to have some form of container to have a faster output while still being recursive? Should I use a helper method? I just recently got into recursive programming and I am having a hard time wrapping my head around this since I've been so used to iterative approaches. Thanks.
Here's my flawed and unfinished code:
public static int fasterFib(int n) {
ArrayList<Integer> results = new ArrayList<Integer>();
if (n <= 2) { // if
return 1;
} else if (results.size() <= n){ // If the list has fewer elems than
results.add(0, 1);
results.add(0, 1);
results.add(results.get(results.size() - 1 + results.get(results.size() - 2)));
return fasterFib(n); // not sure what to do with this yet
} else if (results.size() == n) { // base case if reached elems
return results.get(n);
}
return 0;
}
I think you want to use a Map<Integer, Integer> instead of a List. You should probably move that collection outside of your method (so it can cache the results) -
private static Map<Integer, Integer> results = new HashMap<>();
public static int fasterFib(int n) {
if (n == 0) {
return 0;
} else if (n <= 2) { // if
return 1;
}
if (results.get(n) != null) {
return results.get(n);
} else {
int v = fasterFib(n - 1) + fasterFib(n - 2);
results.put(n, v);
return v;
}
}
This optimization is called memoization, from the Wikipedia article -
In computing, memoization is an optimization technique used primarily to speed up computer programs by keeping the results of expensive function calls and returning the cached result when the same inputs occur again.
You can use Map::computeIfAbsent method (since 1.8) to re-use the already calculated numbers.
import java.util.HashMap;
import java.util.Map;
public class Fibonacci {
private final Map<Integer, Integer> cache = new HashMap<>();
public int fib(int n) {
if (n <= 2) {
return n;
} else {
return cache.computeIfAbsent(n, (key) -> fib(n - 1) + fib(n - 2));
}
}
}
The other way to do this is to use a helper method.
static private int fibonacci(int a, int b, int n) {
if(n == 0) return a;
else return fibonacci(b, a+b, n-1);
}
static public int fibonacci(int n) {
return fibonacci(0, 1, n);
}
How about a class and a private static HashMap?
import java.util.HashMap;
public class Fibonacci {
private static HashMap<Integer,Long> cache = new HashMap<Integer,Long>();
public Long get(Integer n) {
if ( n <= 2 ) {
return 1L;
} else if (cache.containsKey(n)) {
return cache.get(n);
} else {
Long result = get(n-1) + get(n-2);
cache.put(n, result);
System.err.println("Calculate once for " + n);
return result;
}
}
/**
* #param args
*/
public static void main(String[] args) {
Fibonacci f = new Fibonacci();
System.out.println(f.get(10));
System.out.println(f.get(15));
}
}
public class Fibonacci {
private Map<Integer, Integer> cache = new HashMap<>();
private void addToCache(int index, int value) {
cache.put(index, value);
}
private int getFromCache(int index) {
return cache.computeIfAbsent(index, this::fibonacci);
}
public int fibonacci(int i) {
if (i == 1)
addToCache(i, 0);
else if (i == 2)
addToCache(i, 1);
else
addToCache(i, getFromCache(i - 1) + getFromCache(i - 2));
return getFromCache(i);
}
}
You can use memoization (store the values you already have in an array, if the value at a given index of this array is not a specific value you have given to ignore --> return that).
Code:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = Integer.parseInt(s.nextLine());
int[] memo = new int[n+1];
for (int i = 0; i < n+1 ; i++) {
memo[i] = -1;
}
System.out.println(fib(n,memo));
}
static int fib(int n, int[] memo){
if (n<=1){
return n;
}
if(memo[n] != -1){
return memo[n];
}
memo[n] = fib(n-1,memo) + fib(n-2,memo);
return memo[n];
}
Explaination:
memo :
-> int array (all values -1)
-> length (n+1) // easier for working on index
You assign a value to a given index of memo ex: memo[2]
memo will look like [-1,-1, 1, ..... ]
Every time you need to know the fib of 2 it will return memo[2] -> 1
Which saves a lot of computing time on bigger numbers.
private static Map<Integer, Integer> cache = new HashMap<Integer, Integer(){
{
put(0, 1);
put(1, 1);
}
};
/**
* Smallest fibonacci sequence program using dynamic programming.
* #param n
* #return
*/
public static int fibonacci(int n){
return n < 2 ? n : cache.computeIfAbsent(n, (key) -> fibonacci( n - 1) + fibonacci(n - 2));
}
public static long Fib(int n, Dictionary<int, long> dict)
{
if (n <= 1)
return n;
if (dict.ContainsKey(n))
return dict[n];
var value = Fib(n - 1,dict) + Fib(n - 2,dict);
dict[n] = value;
return value;
}

How can I make a recursive version of my iterative method?

I am trying to write a recursive function in Java that prints the numbers one through n. (n being the parameter that you send the function.) An iterative solution is pretty straightforward:
public static void printNumbers(int n){
for(int i = 1; i <= n; i++){
System.out.println(i);
i++;
}
As a new programmer, I'm having troubles figuring out how a recursive version of this method would work.
You are using a for loop that is iterating from i=1 to n. As you want to do this with recursion and it is easier to pass n instead of i and n, we just reverse the whole thing, so we count down n to 1. To keep the order of the prints, we first call the recursive function and print the number after the execution:
public static void printNumbers ( int n )
{
if ( n > 0 )
{
printNumbers( n - 1 ); // n - 2, if the "i++" within the for loop is intended
System.out.println( n );
}
}
For simple iterative -> recursive conversions it is easy to change loops into a format like this:
public static void printNumbers ( int n )
{
int i = 1;
while ( i <= n )
{
System.out.println( i );
i++; // i += 2, if the "i++" within the for loop is intended
}
}
Now you can easily transform that into a recursive function:
public static void printNumbers ( int n, int i )
{
if ( i <= n )
{
System.out.println( i );
i++; // i += 2, if the "i++" within the for loop is intended
printNumbers( n, i );
}
}
Everything else is optimization.
The recursive version needs two arguments (n and i) so make it an auxiliary non-public method and just call it from the public method to start the recursion going:
static void auxPrintNumbers(int n, int i){
if(i <= n) {
System.out.println(i);
auxPrintNumbers(i + 1);
}
}
public static void printNumbers(int n){
auxPrintNumbers(n, 1);
}
Your iterative version has some problems: you are iterating i twice, in the for statement then again at the end of the loop; also you should let i < n be the ending condition of your loop.
To answer your question, obviously the recursive function will have to print out the current number and if the current number hasn't yet reached n, call itself again - so it must take the current number (which we're calling i in the iterative version) as a parameter - or the class needs to hold it as an instance variable, but I'd stick with the parameter.
According to your function that prints every odd number from 1 to n the recursive function should look something like this:
public static void printNumbersRecursive(int n)
{
if (n % 2 == 0) printNumbersRecursive(n - 1);
else if (n > 0)
printNumbersRecursive(n - 2);
System.out.println(n);
}
if it is an error and that you'd want to print EVERY number from 1 to n then:
public static void printNumbersRecursive(int n)
{
if (n > 0)
printNumbersRecursive(n - 1);
System.out.println(n);
}
A class version (just for fun):
class R {
private final int n;
public R (final int n) {
if (n <= 0) {
throw new IllegalArgumentException("n must be positive");
}
this.n = n;
}
#Override
public String toString () {
final StringBuilder sb = new StringBuilder();
if (this.n > 1) {
sb.append(new R(this.n - 1).toString());
}
sb.append(this.n).append(" ");
return sb.toString();
}
}
Used as:
System.out.println(new R(10));
public static void printNumbers(int n){
if( n > 1 ){
printNumbers(n - 1);
}
System.out.println(n);
}
This function calls itself recursively until it reaches n = 1. From this point all values are printed in correct order: 1, 2, 3, ...

Categories