22

我试图回忆一个关于斐波那契递归的算法。以下:

public int fibonacci(int n)  {
  if(n == 0)
    return 0;
  else if(n == 1)
    return 1;
  else
    return fibonacci(n - 1) + fibonacci(n - 2);
}

不是要找的,因为它很贪婪。这将呈指数级增长(只需查看Java 递归斐波那契序列- 初始参数越大,进行的无用调用就越多)。

可能有类似“循环参数移位”的东西,调用先前的斐波那契值将检索值而不是再次计算它。

4

9 回答 9

43

也许是这样的:

int fib(int term, int val = 1, int prev = 0)
{
 if(term == 0) return prev;
 return fib(term - 1, val+prev, val);
}

这个函数是尾递归的。这意味着它可以非常有效地优化和执行。事实上,它被优化成一个简单的循环..

于 2012-12-11T19:11:36.370 回答
10

这类问题是线性递归类型,通过快速矩阵求幂可以最快地解决。这是简明扼要地描述这种方法的博文。

于 2012-12-11T19:24:22.617 回答
8

您可以通过使用记忆化(意思是:存储以前的结果以避免重新计算它们)来做一个非常快速的递归斐波那契版本。例如,这是 Python 中的一个概念证明,其中字典用于保存以前的结果:

results = { 0:0, 1:1 }

def memofib(n):
    if n not in results:
        results[n] = memofib(n-1) + memofib(n-2)
    return results[n]

对于通常会阻塞“正常”递归版本的输入值,它会快速返回。请记住,int数据类型不足以保存大型结果,建议使用任意精度整数。

完全不同的选择 - 重写这个迭代版本......

def iterfib(n):
    a, b = 0, 1
    for i in xrange(n):
        a, b = b, a + b
    return a

...作为尾递归函数,loop在我的代码中调用:

def tailfib(n):
    return loop(n, 0, 1)

def loop(i, a, b):
    if i == 0:
        return a
    return loop(i-1, b, a+b)
于 2012-12-11T19:12:40.507 回答
3

假设您想要第 n 个 fib 号码,然后构建一个包含前面数字的数组

int a[n];
a[0] = 0;
a[1] =1;
a[i] = n[i-1]+n[n-2];
于 2012-12-11T19:11:20.753 回答
3

我发现了关于斐波那契问题的有趣文章

这里的代码片段

# Returns F(n)
def fibonacci(n):
    if n < 0:
        raise ValueError("Negative arguments not implemented")
    return _fib(n)[0]


# Returns a tuple (F(n), F(n+1))
def _fib(n):
    if n == 0:
        return (0, 1)
    else:
        a, b = _fib(n // 2)
        c = a * (2 * b - a)
        d = b * b + a * a
        if n % 2 == 0:
            return (c, d)
        else:
            return (d, c + d)

# added iterative version base on C# example
def iterFib(n):
    a = 0
    b = 1
    i=31
    while i>=0:
        d = a * (b * 2 - a)
        e = a * a + b * b
        a = d
        b = e
        if ((n >> i) & 1) != 0:
            c = a + b;
            a = b
            b = c
        i=i-1
    return a
于 2014-01-03T05:28:55.823 回答
1

JavaScript 中使用递归和延迟初始化缓存以提高效率的示例:

var cache = {};

function fibonacciOf (n) {
  if(n === 0) return 0;
  if(n === 1) return 1;
  var previous = cache[n-1] || fibonacciOf(n-1);
  cache[n-1] = previous;
  return previous + fibonacciOf(n-2);
};
于 2015-06-06T17:06:35.230 回答
0

Duedl0r 的算法翻译成 Swift:

func fib(n: Int, previous: (Int, Int) = (0,1)) -> Int {
    guard n > 0 else { return 0 }
    if n == 1 { return previous.1 }
    return fib(n - 1, previous: (previous.1, previous.0 + previous.1))
}

工作示例:

fib(4)
= fib(4, (0,1) )
= fib(3, (1,1) )
= fib(2, (1,2) )
= fib(1, (2,3) )
= 3
于 2016-01-02T13:55:57.160 回答
0

快速斐波那契计算的一个很好的算法是(在 python 中):

def fib2(n):
    # return (fib(n), fib(n-1))
    if n ==  0: return (0,  1)
    if n == -1: return (1, -1)
    k, r = divmod(n, 2) # n=2k+r
    u_k, u_km1 = fib2(k)
    u_k_s, u_km1_s = u_k**2, u_km1**2  # Can be improved by parallel calls
    u_2kp1 = 4 * u_k_s - u_km1_s + (-2 if k%2 else 2)
    u_2km1 = u_k_s + u_km1_s
    u_2k   = u_2kp1 - u_2km1
    return (u_2kp1, u_2k) if r else (u_2k, u_2km1)

def fib(n):
    k, r = divmod(n, 2) # n=2k+r
    u_k, u_km1 = fib2(k)
    return (2*u_k+u_km1)*(2*u_k-u_km1)+(-2 if k%2 else 2) if r else u_k*(u_k+2*u_km1)

如果您需要非常快速的计算,请链接到 libgmp 并使用 mpz_fib_ui() 或 mpz_fib2_ui() 函数。

于 2016-12-15T23:02:50.963 回答
0

您需要记住计算值以阻止指数增长。

  1. 只需使用数组来存储值。
  2. 如果您已经计算过数组,请检查它。
  3. 如果找到它,请使用它或以其他方式计算并存储它。

这是一个使用内存进行更快递归的工作示例。

计算斐波那契数

于 2017-02-03T16:40:06.740 回答