我在项目欧拉问题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
有没有人对如何优化它有什么想法?提前谢谢。
答案 0 :(得分:1)
您正在搜索x + y = z
您知道z
,因此您可以尝试每x
和y 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毫秒,这甚至没有足够的时间让代码预热。 ;)