Java中的项目Euler 23

时间:2015-12-12 00:52:44

标签: java

我在项目欧拉问题23上遇到了麻烦 - 非丰富的总和。我的代码没有给我正确的答案,我不知道它有什么问题。如果有人也可以帮助我让它跑得更快,那就太好了。

原始问题

完美数字是一个数字,其正确除数的总和恰好等于数字。例如,28的适当除数之和为1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个完美数。

如果n的适当除数之和小于n,则n被称为不足,如果该和超过n则称为n。

由于12是最小的有限数,1 + 2 + 3 + 4 + 6 = 16,可以写成两个有限数之和的最小数是24.通过数学分析,可以看出所有大于28123的整数可以写成两个数字的总和。然而,即使知道不能表示为两个丰富数字之和的最大数量小于该限制,也不能通过分析进一步降低该上限。

找出所有正整数的总和,这些正整数不能写成两个数字的总和。

我的代码的主要问题

  • 错误答案
  • 运行时间过长

我的代码

import java.util.ArrayList;

public class Problem23NonAbundantSums {
    static ArrayList<Integer> abundantNumbers = new ArrayList<Integer>();
    static ArrayList<Integer> sumOfAbundantNumbers = new ArrayList<Integer>();
    static int max = 28123;

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        getAbundantNumbers();
        int temp = 0, sum = 0;
        for (int i = 0; i < abundantNumbers.size(); i++) {
            for (int j = i; j < abundantNumbers.size(); j++) {
                temp = (abundantNumbers.get(i) + abundantNumbers.get(j));
                if (temp < max) {
                    sumOfAbundantNumbers.add(temp);
                }
            }
        }

        for (int i = 1; i <= max; i++) {
            if (sumOfAbundantNumbers.contains(i) == false) {
                sum += i;
            }
        }
        System.out.println(sum);
        long stop = System.currentTimeMillis();
        System.out.println((stop - start) + "ms");

    }

    public static boolean isAbundant(int x) {
        int divisorSum = 0;
        for (int i = 1; i < x; i++) {
            if (x % i == 0) {
                divisorSum += i;
            }
        }
        if (divisorSum > x) {
            return true;
        }
        return false;
    }

    public static void getAbundantNumbers() {
        for (int i = 1; i < max; i++) {
            if (isAbundant(i)) {
                abundantNumbers.add(i);
            }
        }
    }

}

编辑:我收到的是4207994,这是错误的答案。运行需要79081毫秒,我希望它不到1分钟,因为它在Project Euler主页上说所有问题都可以在1分钟内解决。

编辑#2:我实际上发现了if条件下的问题

for (int i = 0; i < abundantNumbers.size(); i++) {
    for (int j = i; j < abundantNumbers.size(); j++) {
        temp = (abundantNumbers.get(i) + abundantNumbers.get(j));
        if (temp < max) {
            sumOfAbundantNumbers.add(temp);
        }
    }
}

temp < max应该是temp <= max

有没有人对如何优化它有什么想法?提前谢谢。

1 个答案:

答案 0 :(得分:1)

您正在搜索x + y = z您知道z,因此您可以尝试每xy which is O(n^2) OR you can try every x and calculate y = z - x {{1}在一个集合中,这是O(n)

此外,您可以搜索最多and lookup的因子,或者您可以搜索最多x的因子,这些因素会为您提供两个因素Math.sqrt(x)i,假设它们不同。

存储一组数字的更有效方法是使用BitSet。这有O(1)查找。您可以使用

循环使用BitSet中预设的值
x / i

如果你做了这一切,它应该在Java中运行不到100毫秒,这甚至没有足够的时间让代码预热。 ;)