我正在研究Project Euler problem #2:
生成Fibonacci序列中的每个新术语 通过添加前两个术语。通过 从1和2开始,前10个术语将是:
1,2,3,5,8,13,21,34,55,89,......
找出序列中所有偶数值的总和,不超过四百万。
我的代码:
public class Two {
public static void main(String[] args) {
Two obj = new Two();
int sum = 0, i = 1;
while (obj.fibonacci(i) < 4000001) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
i++;
}
}
System.out.println(sum);
}
public int fibonacci(int n) {
if (n == 0) {
return -1;
}
if (n == 1) {
return 1;
}
if (n == 2) {
return 3;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
请帮助我运行此代码时出现的问题。它不显示控制台上的输出,总时间超过5分钟
由于
答案 0 :(得分:8)
你被困在一个无限循环中,因为当你的mod 2等于0时你只会增加i。你需要将你的i ++降低。
while (obj.fibonacci(i) <= 4000000) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
}
i++;
}
正如其他评论所提到的,这不是解决斐波纳契问题的最佳方法,但它可以解决您的错误/问题。如果你不明白为什么你应该通过一个调试器,你会发现你使用了很多已经解决的递归调用。由于您在代码中多次调用它(在while语句和if语句中),因此增加了处理时间。
以下是您的斐波那契调用的示例,请注意您如何多次调用相同数字的斐波纳契方法:
1
2
3
2
1
4
3
2
1
2
5
答案 1 :(得分:3)
如上所述,i ++需要移到检查之外,否则你将陷入困境。
但你有一个稍微大一点的问题。 fibonacci sequence以
开头...... 1,2,3,......
而你有...... 1,3,......这意味着你得到的结果不正确。你应该:
// ...
if (n == 2) {
return 2;
// ...
答案 2 :(得分:2)
你的一个问题是你过度使用递归。您应该尝试存储结果,以避免每次重新计算所有内容。
答案 3 :(得分:2)
尽管您的解决方案可能有效,但它重新计算已经获得的结果非常昂贵。
在这种情况下使用递归,要获得fibonacci(4)
的值,您递归地添加先前已经计算过的fibonacci(3)
和fibonacci(2)
的值。
尝试将值存储在列表中,而不是一直重新计算:
List<Long> fibonacci = new ArrayList<Long>();
// First terms
fibonacci.add(-1L); // 0 is dummy, sequence starts at 1
fibonacci.add(1L);
fibonacci.add(2L);
for (int i = 3; fibonacci.get(i - 1) + fibonacci.get(i - 2) < 4000001; i++) {
long u = fibonacci.get(i - 1) + fibonacci.get(i - 2);
fibonacci.add(i, u);
}
使用这种技术,您可以在不到2秒的时间内计算出最大4000000的Fibonacci序列(就像我在计算机上试过的那样)。
然后,只需添加一些代码来计算循环内的总和: - )
答案 4 :(得分:2)
在这种情况下,没有理由存储斐波纳契数的整个序列。你可以简单地沿着序列“走”一些局部变量,随时求和。
int fib2 = 0, fib1 = 1, fib0 = fib1 + fib2;
int sum = 0;
while (fib0 <= N)
{
if (fib0 % 2 == 0) sum += fib0;
fib2 = fib1;
fib1 = fib0;
fib0 = fib1 + fib2;
}
答案 5 :(得分:2)
对@ Blastfurnace解决方案的改进是要注意每三个值都是均匀的。
public static void main(String[] args) {
long sum = 0;
int runs = 30000;
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long start = System.nanoTime();
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long time = System.nanoTime() - start;
System.out.println(sum+" took "+time/runs+" ns avg");
}
private static long sumEvenFib() {
int sum = 0;
for(int f1 = 1, f2 = 2;f2 < 4000001;) {
sum += f2;
int f3 = f1 + f2;
f1 = f3 + f2;
f2 = f1 + f3;
}
return sum;
}
在我的旧实验室上,这需要大约40 ns。或0.000000040秒。
答案 6 :(得分:0)
我认为这个问题已经含糊不清了。 所有均值的总和应该低于400万,或者最大均值应该低于400万?
答案 7 :(得分:0)
我认为你可以通过下一步方式改善斐波纳契:
def fib(x)
if(x==0 or x==1) then
return x;
end
a,b = 0,1
(x-1).times{ a,b = b,a+b; }
return b;
end
换句话说,将递归转换为迭代。