简体   繁体   English

在Java中使用递归的主要因素

[英]Prime factors using recursion in Java

I'm having trouble with recursion in java. 我在使用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. 通常有两种形式,一种提供用户界面,另一种通常是private ,实际上执行递归功能。

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. 您可以通过重载来添加f作为参数,并添加接受它的私有方法,并从“ main”公共方法中调用该私有方法。

In the private method, you have 3 cases: 在私有方法中,您有3种情况:

  1. stop clause: n==1: create a new empty list stop子句:n == 1:创建一个新的空列表
  2. n%f == 0: recurse with n'=n/f, f'=f, and add f to the list. n%f == 0:递归n'= n / f,f'= f,然后将f添加到列表中。
  3. n%f != 0: recurse with n'=n, f'=f+1, don't add anything to the list. n%f!= 0:使用n'= n,f'= f + 1递归,不向列表添加任何内容。

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) 在stop子句中将ArrayList实现切换到LinkedList (用于性能问题)
  2. add items with factors.add(0, f); factors.add(0, f);添加项目factors.add(0, f); instead factors.add(f) 而是factors.add(f)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM