【问题标题】:How would I speed up this program?我将如何加快这个程序?
【发布时间】:2017-02-20 13:02:06
【问题描述】:

我目前正在尝试解决ProjectEuler problem 问题,除了速度之外,我已经把所有东西都搞定了。我几乎可以肯定程序执行如此缓慢的原因是由于嵌套循环。我想就如何加快速度提供一些建议。我是一个新手程序员,所以我对很多更高级的方法/主题并不熟悉。

public class Problem12 {

    public static void main(String[] args) {
        int num;

        for (int i = 1; i < 15000; i++) {
            num = i * (i + 1) / 2;
            int counter = 0;

            for (int x = 1; x <= num; x++) {
                if (num % x == 0) {
                    counter++;
                }
            }
            System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
        }
    }
}

编辑:下面是速度更快的新代码。也删除了恒定行打印以加快速度。

public class Problem12 {

    public static void main(String[] args) {
        int num;

        outerloop:
        for (int i = 1; i < 25000; i++) {
            num = i * (i + 1) / 2;
            int counter = 0;

            double root = Math.sqrt(num);
            for (int x = 1; x < root; x++) {
                if (num % x == 0) {
                    counter += 2;
                    if (counter >= 500) {
                        System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers.");
                        break outerloop;
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 尝试使用更快的语言,如 C,并尝试使用位移而不是除法和乘法,如果它们在 Java 中可用
  • 这个算法真的有效吗?就像如果i=3 然后num=6 然后counter=4 这是不正确的
  • @ShaheAnsar 如果你不知道是否支持位移,你怎么能假设 C 比 Java 快?
  • @afsafzal 你的意思是“这是正确的”。 6 的预期值为 1, 2, 3, 6,如 OP 链接到的问题的描述中所示
  • 您将打印 15000 行。任何打印都比简单的语句花费更多的时间,所以如果你想计时,首先注释掉打印。

标签: java performance loops nested-loops


【解决方案1】:

首先,在查看除数时,您永远不需要超过数字的平方根,因为平方根以下的每个除数都有一个等价的上面。

n = a * b => a <= sqrt(n) or b <= sqrt(n)

那你需要计算除法的另一边:

double root = Math.sqrt(num);
for (int x = 1; x < root; x++) {
    if (num % x == 0) {
        counter += 2;
    }
}

平方根很特殊,因为它是整数时只计算一次:

if ((double) ((int) root) == root) {
    counter += 1;
}

【讨论】:

  • 这成功了。但是,我不确定如何。您介意详细说明一下为什么会这样吗?
  • 每个除数成对工作,这就是我们将每个除数计算两次的原因。对于每一对,一个元素低于平方根,另一个高于平方根。这很容易看出:如果两个元素都在上面,那么结果也在上面。如果两者都低于,则结果也低于。示例:10 = 2*5 = 1*10。 2和1低于3.16,5和10高于。
  • 尽管如此,我错了没有三角形 平方数,现在编辑
【解决方案2】:

您只需要对数字进行因式分解。 p^a * q^b * r^c(a+1)*(b+1)*(c+1) 除数。下面是使用这个想法的一些基本实现:

static int Divisors(int num) {
    if (num == 1) {
        return 1;
    }

    int root = (int) Math.sqrt(num);
    for (int x = 2; x <= root; x++) {
        if (num % x == 0) {
            int c = 0;
            do {
                ++c;
                num /= x;
            } while (num % x == 0);
            return (c + 1) * Divisors(num);
        }
    }

    return 2;
}

public static void test500() {
    int i = 1, num = 1;
    while (Divisors(num) <= 500) {
        num += ++i;
    }

    System.out.println("\nFound: [" + i + "] - " + num);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    相关资源
    最近更新 更多