0

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]
1
  • What trouble are you having exactly? What have you tried? Commented May 14, 2015 at 9:08

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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:

  1. stop clause: n==1: create a new empty list
  2. n%f == 0: recurse with n'=n/f, f'=f, and add f to the list.
  3. 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:

  1. switch ArrayList implementation to LinkedList in stop clause (for performance issues)
  2. add items with factors.add(0, f); instead factors.add(f)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.