【问题标题】:Project Euler 23 in JavaJava中的Euler 23项目
【发布时间】:2015-12-12 00:52:44
【问题描述】:

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

原来的问题

完美数是一个数,它的真因数之和正好等于这个数。例如,28 的因数之和为 1 + 2 + 4 + 7 + 14 = 28,这意味着 28 是一个完美数。

如果一个数 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 &lt; max 应该是temp &lt;= max

有人对如何优化它有想法吗?提前致谢。

【问题讨论】:

  • 你得到什么答案?您是否尝试过使用调试器?您希望代码运行多快(Big O-wise)?它现在的运行速度有多快?如果没有足够的上下文,很难回答一个问题。
  • 我会确保它首先计算出正确的答案。如果它错了,需要多长时间都没关系。
  • 解决方案需要时间,我认为这很正常,至少我的做到了。正如彼得所说,最好是尝试使用小数字,在启动更大数字的程序之前检查它是否有效。我在这里给你一个提示:我使用了一个列表倒出丰富的数字和一个所有数字 0

标签: java


【解决方案1】:

你正在搜索 x + y = z 你知道 z 所以你可以尝试每个 xy which is O(n^2) OR you can try everyxand calculatey = z - xand lookupy` 在一个集合中,这是 O(n )

您还可以搜索高达x 的因子,或者您可以搜索高达Math.sqrt(x) 的因子,这会给出两个因子ix / i,假设它们是不同的。

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

循环遍历 BitSet 中预设的值
for (int j = abundant.nextSetBit(0); j > 0; j = abundant.nextSetBit(j+1)) {

如果您执行所有这些操作,它应该在 Java 中运行不到 100 毫秒,这甚至没有足够的时间让代码预热。 ;)

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多