使用递归查找斐波那契数列中的数字 - 如何使其更快?

Finding the numbers in the Fibonacci sequence using recursion - how to make it faster?

我的查找斐波那契数列中的数字的代码工作正常,但它真的很慢。 (几乎不可能找到超过 n=55 的数字)。我哪里弄错了?

public static void main(String[] args) {

    for (; ; ) {
        System.out.println("The value of the fibonacci sequence ");
        Scanner numer = new Scanner(System.in);
        long n = numer.nextLong();
        long result = Fib(n);
        System.out.println(result);

    }
}


private static long Fib(long n) {
    if (n <= 0) { System.out.println("Error"); return 0;}
    else if (n == 1 | n == 2) return 1;
    else return Fib(n-1)+ Fib(n-2) ;

}

你知道你为每个 k 计算了多少次 fib(k) 吗?如果你想让你的程序运行快,不要那么盲目地使用递归,而是使用循环:

private static long Fib(long n) {
    long prev = 1;
    long current = 1;
    if (n <= 0) { System.out.println("Error"); return 0;}
    if (n == 1 | n == 2) return 1;
    for (int i = 3; i <= n; i++) {
        long next = prev + current;
        prev = current;
        current = next;
    }
    return current;

}

如果你只想通过递归来解决这个问题,那么你需要存储已经计算的结果。它可以通过记忆或使用惰性动态编程来完成,而且它比只使用循环要难得多。

即使@Jason 提出了改进建议,这仍然是一个 指数时间 复杂度为 O(2^N) 的算法。

为了将时间复杂度降低到O(N),也称为线性时间,我提出了以下方法(称为“memoization ",因为我们保存了我们计算的每个值,并在每次被询问时直接 return 它 O(1) 时间,因此堆栈帧将少得多,并且最多会随着 [=26= 的值线性增加]).

public static void main(String[] args) {
    // receive customer input
    HashMap<Long, Long> map = new HashMap<>();
    long result = Fib(n, map);
}

private long Fib(long n, HashMap<Long, Long> map) {
    if (n <= 0) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    if (map.containsKey(n)) {
        return map.get(n);
    } else {
        map.put(n, Fib(n - 1, map) + Fib(n - 2, map));
        return map.get(n);
    }

}

您可以通过在 Leetcode 的斐波那契练习中提交它们来比较这两个解决方案。

此外,上面 link 中的 "Solution" 选项卡下解释了这两种方法(您的方法和我的类似的记忆方法),您可以在其中了解有关时间复杂度的更多信息。