代码工作速度非常慢,不打印输出

时间:2010-09-18 10:01:34

标签: java

我正在研究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分钟

由于

8 个答案:

答案 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

换句话说,将递归转换为迭代。