【问题标题】:Optimizing recursive method优化递归方法
【发布时间】:2014-10-19 20:24:42
【问题描述】:

我有一些代码需要运行一些相当大的数字,它涉及递增到递归方法,因此速度非常慢,以至于我什至无法得到我想要的答案。有人可以帮我优化吗?不过我是初学者,所以我不能做任何非常复杂/困难的事情。

public class Euler012{
    public static void main(String[]args){
        int divisors=0;
        for(long x=1;divisors<=501;x++){
            divisors=1;
            long i=triangle(x);
            for(int n=1;n<=i/2;n++){
                if(i%n==0){
                    divisors++;
                }
            }
            //System.out.println(divisors+"\n"+ i);
            System.out.println(i+": " + divisors);
        }
    }
    public static long triangle(long x){
        long n=0;
        while(x>=0){
            n+=x;
            x--;
            triangle(x);
        }
        return n;
    }
 } 

【问题讨论】:

  • 三角形(x)应该返回什么?其中的递归调用似乎是一个错误,因为您总是使用相同的 x 值调用它,所以它会导致无限递归。
  • @Eran - 该值在递归调用之前递减。
  • @DonRoby 哦,我明白了。但是,OP 仍然没有对 triangle 的返回值做任何事情,那么递归调用的意义何在?
  • @Eran - 这是真的,很可能是他的问题的一部分。
  • @Eran 函数返回序列中的下一个“三角形”数字。 (在while循环之后使用return语句)。三角形数 n 是直到并包括 n 在内的每个数的总和。

标签: java optimization recursion


【解决方案1】:

首先:我不认为这是一个优化问题,因为它是一项小任务,但正如 cmets 中提到的,你做了很多不必要的事情。

好的,现在让我们看看你可以在哪里优化:

递归

递归通常性能很差,特别是如果您不保存值,这在您的示例中是可能的。

例如:具有保存值的递归三角形数函数

private static ArrayList<Integer> trianglenumbers = new ArrayList<>();

public static int triangleNumber(int n){
    if(trianglenumbers.size() <= n){
        if(n == 1)
            trianglenumbers.add(1);
        else
            trianglenumbers.add(triangleNumber(n-1) + n);
    }
    return trianglenumbers.get(n-1);
}

但正如@RichardKennethNiescior 所述,您可以简单地使用公式: (n² + n)/2

但是在这里我们也可以进行优化! 你不应该做/2,而是*0.5,甚至&gt;&gt;1(右移) 但大多数编译器都会为你做到这一点,所以不需要让你的代码不可读

你的主要方法

public static void main(String[]args){
    int divisors = 0; //skip the = 0
    for(long x=1;divisors<=501;++x){ // ++x instead of x++
        divisors=0;
        long i=(x*x + x) >> 1; // see above, use the one you like more
        /*how many divisors*/
        if(i == 1) divisors = 1;
        else{ /*1 is the only number with just one natural divisor*/
            divisors = 2; // the 1 and itself
            for(int n = 2; n*n <= i; ++n){
                if(n*n == i) ++divisors;
                else if(i%n == 0) divisors += 2;
            }
        }
        System.out.println(i+": " + divisors);
    }
}

解释了 ++x 而不是 x++ 的东西here

有多少除数部分: 除了 1 之外的每个数字都至少有 2 个除数(素数、数字本身和一个) 要检查一个数字有多少个除数,我们只需要去数字的根 (例如 36 -> 它的平方根是 6) 36 有 9 个除数(4 对){1 和 36、2 和 18、3 和 12、4 和 8、6(和 6)}

1 和 36 被跳过 (for(**int n = 2**)) 但计入 divisors = 2 和 pares 2、3 和 4 将除数的数量增加了 2 如果它是一个平方数 (n*n == i) 那么我们加起来 1

【讨论】:

    【解决方案2】:

    您不必每次都从头开始生成新的三角形数,如果将值保存到变量中,然后在下一次迭代时将 x 添加到它,则根本不需要三角形方法。

    【讨论】:

      猜你喜欢
      • 2021-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 2016-07-28
      • 2012-08-11
      • 2014-01-10
      相关资源
      最近更新 更多