【问题标题】:Recursively Factoring with Java, dealing with StackOverflow用Java递归分解,处理StackOverflow
【发布时间】:2015-03-08 22:16:00
【问题描述】:

我需要编写一个方法,将数字递归分解为 1234567890,我当前的应用程序在抛出 StackOverflowError 之前只处理小数字。我知道我的问题是递归调用太多,但我不知道如何减少我的调用次数。

它需要是递归的。

我认为解决方案与我的算法背后的数学有关。我看过不同的迭代解决方案,但我似乎无法用更少的调用来递归地执行它。代码:

public static boolean isPrime(int input, int i) {
    if (i <= 2) {
        return true;
    }
    if (input % i != 0) {
        return isPrime(input, i-1);
    } else {
        factors(input, i);
        return false;
    }
}
public static void factors(int input, int i) {
    if (i <= 1) {
        System.out.printf(" %d", 1);
    } else {
        if (input % i == 0) {
            System.out.printf(" %d", i);
        }
        factors(input, i - 1);
    }
}

并且开始于:

System.out.println("What integer would you like to factor?");
    num1 = scan.nextInt();
    if(isPrime(num1, num1 - 1)){
        System.out.println("Input is a prime number");
    } else {
        System.out.println(" factors\nInput isn't a prime number.");
    }

【问题讨论】:

  • 如何开始这个方法?你能提供一些例子吗?您是否必须使用递归,因为这可以在完全没有递归的情况下完成。我建议您使用实际代码,因为这仍然无法编译。
  • 我添加了使用它的部分,它应该也可以工作。它必须是递归的。
  • 试试 isPrime(num1, (int) Math.sqrt(num1)) 它将有 N^0.5 而不是 N 的深度。如果你需要两者,你可以打印出 in / i 作为因子。
  • 它需要处理大数字(10 位),但它会在 ~6000 次迭代后抛出 stackoverflow。
  • 简单的解决方案是使用堆栈深度为 1 或 2 的迭代。如果您还必须使用迭代来避免某些递归深度,我不清楚使用递归的意义何在。

标签: java recursion stack-overflow


【解决方案1】:

将您的 Factor 方法更改为非递归(如果不需要递归)

 public static void factors(int input, int i) {
     for(int j = i; j >= 1; j--) {
         if (input % j == 0)
             System.out.println(j);
     } 
}

已编辑:如下所示是解决此问题的递归方法。

public void isPrime(int num1)
{
int count=countFactors(num1);
if(count==0)
System.out.println("No is prime");
}

public int countFactors(int num,int i)
{

if(i>num/2)return 0;
if(num%i==0)
{
System.out.println(i);
return 1+countFactors(num,i+1);
}

}

【讨论】:

  • 我的逻辑怎么错了?它适用于较小的数字。在寻找因素方面还是在执行递归方面?
  • @Algorithmist:像您描述的简单方法在 10 位数字上是不可行的。 Plus 是列出因子,这与分解不同。
  • 为递归方法添加了新逻辑。
【解决方案2】:

我认为它需要递归的原因是因为它是一个家庭作业问题。因此,我不会告诉你怎么做,而是告诉你你的数学有什么问题。您的算法看起来部分正确,除了(a)您忘记将“n”除以您找到的每个因子,以及(b)您正在寻找从大数向下而不是从小数向上的因子。最好开始和 2 并计数到 sqrt(n) 虽然这不会解决堆栈溢出问题。

您需要在循环中查找因子,并保留使用递归(如果您真的需要使用它)在除以素因子后对剩余数字进行因式分解。因为你不想通过一个 6 位数的质数,然后需要 100 万级堆栈来证明它没有因数。即这需要在一个简单的循环而不是递归中:

return isPrime(输入, i-1);

...这可以是递归的:

因素(输入,i);

【讨论】:

    【解决方案3】:

    增加你的java中的堆栈大小。 你可以搜索如何增加堆栈大小

    【讨论】:

      【解决方案4】:

      您可以使用尾调用优化(Java 不会为您做)

      public static void factors(int input, int i) {
          while(i > 1) {
              if (input % i == 0) {
                  System.out.printf(" %d", i);
              }
              i = i - 1;
          }
          System.out.printf(" %d", 1);
      }
      

      当然你不再做递归了。

      【讨论】:

        【解决方案5】:

        您似乎用于素数检查的算法是trial division algorithm

        有很多other methods,但是,按照这个策略,有一个命题声明你只需要检查到 n 的平方根,其中 n 是你的input。此外,您的谓词没有正确处理负整数(返回 true)。

        因此,在第一种方法中,您的算法将是:

        public static boolean isPrime(int n) {
            if (n < 2) { return false; }
            return helper_isPrime(n, 2, (int) Math.sqrt(n));
        }
        

        地点:

        private static boolean helper_isPrime(int n, int i, int max) {
            if (i > max) { return true; }
            if (n % i == 0) { return false; }
            return helper_isPrime(n, i+1, max);
        }
        

        用两种方法分离n &lt; 2 的测试。请注意,n 将保持不变,因此只需在流程开始时执行一次测试。

        此外,保理被抛在后面。在我看来,应该从外面问,像这样:

        System.out.println("What integer would you like to factor?");
        num1 = scan.nextInt();
        if(isPrime(num1)){
            System.out.println("Input is a prime number");
        } else {
            System.out.println("Input isn't a prime number.");
            int[] fac = factor(n);
            System.out.println("Factors: " + fac.toString());
        }
        

        factor 是您最喜欢的因子算法。因式分解算法可能会发现它是使用素数执行的最坏情况,但是,由于已经进行了测试,并且由于仅当数字 不是 素数时才调用该算法,因此这种情况不会不会发生。

        【讨论】:

          猜你喜欢
          • 2017-10-04
          • 1970-01-01
          • 1970-01-01
          • 2014-09-05
          • 2016-07-19
          • 1970-01-01
          • 2014-10-31
          • 2012-10-04
          • 2011-12-26
          相关资源
          最近更新 更多