【问题标题】:Fibonacci using a recursive method gives me stack overflow使用递归方法的斐波那契给了我堆栈溢出
【发布时间】:2019-03-01 00:59:59
【问题描述】:
public static int rFib(int n) {

    if(n == 0) {
        return 0;
    }

    if(n == 1) {
        return 1;
    }  

    return n + rFib(n-1);
}

我正在尝试找到将在 60 秒内计算的最大数字。然后我将使用迭代方法进行比较。任何大于 10,000 的数字都会产生堆栈溢出错误。我该如何避免这种情况?

【问题讨论】:

  • 尝试将一些结果存储在数组 fib[i] 中,以减少不必要的方法调用的成本吗?
  • “如何避免这种情况?” 不要使用递归。 --- 您可以增加堆栈大小,但这只会提高限制。无需使用递归即可计算斐波那契。
  • 10,000 gives a stack-overflow error. - 会发生什么?
  • @buræquete 这将提高性能,但不会修复堆栈溢出错误。如果 number 大于 10,000,结果是调用堆栈 10,000 深,当然这会导致堆栈溢出错误。
  • 仅供参考:您的实现是错误的。你实现了f(n) = n + f(n-1),但是斐波那契函数是f(n) = f(n-1) + f(n-2)

标签: java recursion stack-overflow fibonacci


【解决方案1】:

解决此递归问题的一种方法是使用动态规划来中断递归。例如,memoization 可以应用并允许您像这样实现它

private static Map<Integer, Integer> memo = new HashMap<>();
static {
    memo.put(0, 0);
    memo.put(1, 1);
}

public static int rFib(int n) {
    if (memo.containsKey(n)) {
        return memo.get(n);
    }
    int r = rFib(n - 2) + rFib(n - 1);
    memo.put(n, r);
    return r;
}

【讨论】:

    【解决方案2】:

    不幸的是,您遇到了这个问题,它既是理解递归的最常用的例子,也是应用递归的最糟糕的应用程序。

    从斐波那契理解递归真的很简单,因为它是一个非常简单的递归算法,你可以向某人解释并理解......这意味着它非常适合编程递归,对吧?不幸的是,没有。

    如果我要告诉你一些你已经知道的事情,我深表歉意,但我知道斐波那契是入门编程中的第一个例子,所以我假设你就是从那里来的。

    编程中有一种东西叫做堆栈。它的字面意思是这样的,因为它就像一摞纸。当您调用一个函数时,它会将调用该函数、传递参数以及知道如何从函数返回(以及其他一些管理内容)所需的所有信息放入堆栈。当该函数递归调用自身时,它将另一张工作表放在堆栈顶部。然后该函数放置 另一个 工作表。这些工作表在函数完成之前不会被删除......但是由于一个函数无法在另一个函数完成之前完成,它只会不断增长。

    而且堆栈只有这么大。故意。为了避免这个问题。

    通常情况下,递归不用于解决如此深层次的问题。 (尾调用递归的人:忽略这个;如果你不知道尾调用递归是什么:也忽略这个。)

    解决这个问题的方法是不要这样做。人们普遍认为,在几乎所有任意递归函数应用程序中,for 循环都会更好(更快)工作。

    【讨论】:

    • 不需要道歉,我是学生,还在学习。我同意并且不会对这个问题使用递归,但它被指示这样做。我正在上一门算法设计课,这是为了展示递归并不总是最好的。我们只是在学习动态编程,所以我将尝试采用这种方法。感谢您的意见!
    猜你喜欢
    • 2012-05-06
    • 2014-11-14
    • 1970-01-01
    • 2011-03-24
    • 2018-02-17
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多