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)
Related
I need to sum the three consecutive elements of an array when appending numbers to the same array dynamically and return true if the sum is equal to the argument value. I have already written the code below and it all return required output but it fails for some test cases( I don't have the the exact test cases), Can anybody tell me what exact scenario which my programme can be failed?
import java.util.LinkedList;
import java.util.List;
public class Test {
List<Integer> mergeList = new LinkedList<Integer>();
List<List<Integer>> allList = new LinkedList<List<Integer>>();
List<Integer> tail;
int from = 0;
int to = 0;
public void addLast(int[] list) {
allList.removeAll(allList);
for(int i : list) {
mergeList.add(i);
}
if (mergeList.size() > 0) {
int j = 0;
while(to < mergeList.size()){
from = j;
to = j + 3;
tail = mergeList.subList(from, to);
j++;
allList.add(tail);
}
}
}
public boolean containsSum3(int sum) {
boolean retVal = false;
for (List<Integer> sum3List : allList) {
if (sum3List.stream().mapToInt(Integer::intValue).sum() == sum) {
retVal = true;
}
}
return retVal;
}
public static void main(String[] args) {
Test s = new Test();
s.addLast(new int[] { 1, 2, 3 });
System.out.println(s.containsSum3(6));
System.out.println(s.containsSum3(9));
s.addLast(new int[] { 4 });
System.out.println(s.containsSum3(9));
s.addLast(new int[] { 5, 2});
System.out.println(s.containsSum3(11));
s.addLast(new int[] { 0, -1 });
System.out.println(s.containsSum3(7));
System.out.println(s.containsSum3(2));
}
}
Output:
true
false
true
true
true
false
I generated large random collections of integers and couldn't find any obvious cases your code fails for beyond the insufficient elements. Incidentally, the function I wrote to check if a list has any consecutive n elements that sum to a given value was:
public static boolean containsSum(List<Integer> list, int sum, int n) {
return IntStream.range(0, list.size() - n + 1)
.anyMatch(i -> list.subList(i, i + n).stream()
.reduce(0, Integer::sum) == sum);
}
I can't see any reason for your code that keeps all the list of lists: the space / time tradeoff doesn't make a lot of sense. I suggest you could simplify addLast to just add the elements to mergeList. There are a bunch of stylistic issues with your code but I'm sure you'll work those out in your own time.
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/
I need a task about finding Fibonacci Sequence for my independent project in Java. Here are methods for find.
private static long getFibonacci(int n) {
switch (n) {
case 0:
return 0;
case 1:
return 1;
default:
return (getFibonacci(n-1)+getFibonacci(n-2));
}
}
private static long getFibonacciSum(int n) {
long result = 0;
while(n >= 0) {
result += getFibonacci(n);
n--;
}
return result;
}
private static boolean isInFibonacci(long n) {
long a = 0, b = 1, c = 0;
while (c < n) {
c = a + b;
a = b;
b = c;
}
return c == n;
}
Here is main method:
long key = getFibonacciSum(n);
System.out.println("Sum of all Fibonacci Numbers until Fibonacci[n]: "+key);
System.out.println(getFibonacci(n)+" is Fibonacci[n]");
System.out.println("Is n2 in Fibonacci Sequence ?: "+isInFibonacci(n2));
Codes are completely done and working. But if the n or n2 will be more than normal (50th numbers in Fib. Seq.) ? Codes will be runout. Are there any suggestions ?
There is a way to calculate Fibonacci numbers instantaneously by using Binet's Formula
Algorithm:
function fib(n):
root5 = squareroot(5)
gr = (1 + root5) / 2
igr = 1 - gr
value = (power(gr, n) - power(igr, n)) / root5
// round it to the closest integer since floating
// point arithmetic cannot be trusted to give
// perfect integer answers.
return floor(value + 0.5)
Once you do this, you need to be aware of the programming language you're using and how it behaves. This will probably return a floating point decimal type, whereas integers are probably desired.
The complexity of this solution is O(1).
Yes, one improvement you can do is to getFibonacciSum(): instead of calling again and again to isInFibonacci which re-calculates everything from scratch, you can do the exact same thing that isInFibonacci is doing and get the sum in one pass, something like:
private static int getFibonacciSum(int n) {
int a = 0, b = 1, c = 0, sum = 0;
while (c < n) {
c = a + b;
a = b;
sum += b;
b = c;
}
sum += c;
return sum;
}
Well, here goes my solution using a Map and some math formulas. (source:https://www.nayuki.io/page/fast-fibonacci-algorithms)
F(2k) = F(k)[2F(k+1)−F(k)]
F(2k+1) = F(k+1)^2+F(k)^2
It is also possible implement it using lists instead of a map but it is just reinventing the wheel.
When using Iteration solution, we don't worry about running out of memory, but it takes a lot of time to get fib(1000000), for example. In this solution we may be running out of memory for very very very very big inputs (like 10000 billion, idk) but it is much much much faster.
public BigInteger fib(BigInteger n) {
if (n.equals(BigInteger.ZERO))
return BigInteger.ZERO;
if (n.equals(BigInteger.ONE) || n.equals(BigInteger.valueOf(2)))
return BigInteger.ONE;
BigInteger index = n;
//we could have 2 Lists instead of a map
Map<BigInteger,BigInteger> termsToCalculate = new TreeMap<BigInteger,BigInteger>();
//add every index needed to calculate index n
populateMapWhitTerms(termsToCalculate, index);
termsToCalculate.put(n,null); //finally add n to map
Iterator<Map.Entry<BigInteger, BigInteger>> it = termsToCalculate.entrySet().iterator();//it
it.next(); //it = key number 1, contains fib(1);
it.next(); //it = key number 2, contains fib(2);
//map is ordered
while (it.hasNext()) {
Map.Entry<BigInteger, BigInteger> pair = (Entry<BigInteger, BigInteger>)it.next();//first it = key number 3
index = (BigInteger) pair.getKey();
if(index.remainder(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
//index is divisible by 2
//F(2k) = F(k)[2F(k+1)−F(k)]
pair.setValue(termsToCalculate.get(index.divide(BigInteger.valueOf(2))).multiply(
(((BigInteger.valueOf(2)).multiply(
termsToCalculate.get(index.divide(BigInteger.valueOf(2)).add(BigInteger.ONE)))).subtract(
termsToCalculate.get(index.divide(BigInteger.valueOf(2)))))));
}
else {
//index is odd
//F(2k+1) = F(k+1)^2+F(k)^2
pair.setValue((termsToCalculate.get(index.divide(BigInteger.valueOf(2)).add(BigInteger.ONE)).multiply(
termsToCalculate.get(index.divide(BigInteger.valueOf(2)).add(BigInteger.ONE)))).add(
(termsToCalculate.get(index.divide(BigInteger.valueOf(2))).multiply(
termsToCalculate.get(index.divide(BigInteger.valueOf(2))))))
);
}
}
// fib(n) was calculated in the while loop
return termsToCalculate.get(n);
}
private void populateMapWhitTerms(Map<BigInteger, BigInteger> termsToCalculate, BigInteger index) {
if (index.equals(BigInteger.ONE)) { //stop
termsToCalculate.put(BigInteger.ONE, BigInteger.ONE);
return;
} else if(index.equals(BigInteger.valueOf(2))){
termsToCalculate.put(BigInteger.valueOf(2), BigInteger.ONE);
return;
} else if(index.remainder(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
// index is divisible by 2
// FORMUMA: F(2k) = F(k)[2F(k+1)−F(k)]
// add F(k) key to termsToCalculate (the key is replaced if it is already there, we are working with a map here)
termsToCalculate.put(index.divide(BigInteger.valueOf(2)), null);
populateMapWhitTerms(termsToCalculate, index.divide(BigInteger.valueOf(2)));
// add F(k+1) to termsToCalculate
termsToCalculate.put(index.divide(BigInteger.valueOf(2)).add(BigInteger.ONE), null);
populateMapWhitTerms(termsToCalculate, index.divide(BigInteger.valueOf(2)).add(BigInteger.ONE));
} else {
// index is odd
// FORMULA: F(2k+1) = F(k+1)^2+F(k)^2
// add F(k+1) to termsToCalculate
termsToCalculate.put(((index.subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2)).add(BigInteger.ONE)),null);
populateMapWhitTerms(termsToCalculate,((index.subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2)).add(BigInteger.ONE)));
// add F(k) to termsToCalculate
termsToCalculate.put((index.subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2)), null);
populateMapWhitTerms(termsToCalculate, (index.subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2)));
}
}
This method of solution is called dynamic programming
In this method we are remembering the previous results
so when recursion happens then the cpu doesn't have to do any work to recompute the same value again and again
class fibonacci
{
static int fib(int n)
{
/* Declare an array to store Fibonacci numbers. */
int f[] = new int[n+1];
int i;
/* 0th and 1st number of the series are 0 and 1*/
f[0] = 0;
f[1] = 1;
for (i = 2; i <= n; i++)
{
/* Add the previous 2 numbers in the series
and store it */
f[i] = f[i-1] + f[i-2];
}
return f[n];
}
public static void main (String args[])
{
int n = 9;
System.out.println(fib(n));
}
}
public static long getFib(final int index) {
long a=0,b=0,total=0;
for(int i=0;i<= index;i++) {
if(i==0) {
a=0;
total=a+b;
}else if(i==1) {
b=1;
total=a+b;
}
else if(i%2==0) {
total = a+b;
a=total;
}else {
total = a+b;
b=total;
}
}
return total;
}
I have checked all solutions and for me, the quickest one is to use streams and this code could be easily modified to collect all Fibonacci numbers.
public static Long fibonaciN(long n){
return Stream.iterate(new long[]{0, 1}, a -> new long[]{a[1], a[0] + a[1]})
.limit(n)
.map(a->a[0])
.max(Long::compareTo)
.orElseThrow();
}
50 or just below 50 is as far as you can go with straight recursive implementation. You can switch to iterative or dynamic programming (DP) approaches if you want to go much higher than that. I suggest learning about those from this: https://www.javacodegeeks.com/2014/02/dynamic-programming-introduction.html. And don't forget to look the a solution in the comment by David therein, real efficient. The links shows how even n = 500000 can be computed instantaneously using the DP method. The link also explains the concept of "memoization" to speed up computation by storing intermediate (but later on re-callable) results.
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;
}
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, ...