Fast Fibonacci recursion

2019-01-10 17:26发布

I'm trying to recall an algorithm on Fibonacci recursion. The following:

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

is not what I'm looking for because it's greedy. This will grow exponentially (just look at Java recursive Fibonacci sequence - the bigger the initial argument the more useless calls will be made).

There is probably something like a "cyclic argument shift", where calling previous Fibonacci value will retrieve value instead of calculating it again.

9条回答
Evening l夕情丶
2楼-- · 2019-01-10 18:26

This kind of problems are linear recurrence types and they are solved fastest via fast matrix exponentiation. Here's the blogpost that describes this kind of approach concisely.

查看更多
The star\"
3楼-- · 2019-01-10 18:27

You can do a pretty fast version of recursive Fibonacci by using memoization (meaning: storing previous results to avoid recalculating them). for example, here's a proof of concept in Python, where a dictionary is used for saving previous results:

results = { 0:0, 1:1 }

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

It returns quickly for input values that would normally block the "normal" recursive version. Just bear in mind that an int data type won't be enough for holding large results, and using arbitrary precision integers is recommended.

A different option altogether - rewriting this iterative version ...

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

... as a tail-recursive function, called loop in my code:

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)
查看更多
Bombasti
4楼-- · 2019-01-10 18:30

An example in JavaScript that uses recursion and a lazily initialized cache for added efficiency:

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);
};
查看更多
登录 后发表回答