Reputation: 3
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]
Upvotes: 0
Views: 7808
Reputation: 178461
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:
f
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:
ArrayList
implementation to LinkedList
in stop clause (for performance issues)factors.add(0, f);
instead factors.add(f)
Upvotes: 1
Reputation: 65811
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.
Upvotes: 2