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条回答
Emotional °昔
2楼-- · 2019-01-10 18:08

maybe like this:

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

this function is tail recursive. this means it could be optimized and executed very efficiently. In fact, it gets optimized into a simple loop..

查看更多
趁早两清
3楼-- · 2019-01-10 18:08

I found interesting article about fibonacci problem

here the code snippet

# 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
查看更多
神经病院院长
4楼-- · 2019-01-10 18:12

You need to memorize the calculated value in order to stop exponential growth.

  1. Just use an array to store the value.
  2. Check the array if you have already calculate it.
  3. If it finds it,use it or otherwise calculate it and store it.

Here is an working example for faster recursion using memory.

Calculating fibonacci number

查看更多
相关推荐>>
5楼-- · 2019-01-10 18:18

A good algorithm for fast fibonacci calculations is (in 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)

If you need very fast computation, links to the libgmp and use mpz_fib_ui() or mpz_fib2_ui() functions.

查看更多
地球回转人心会变
6楼-- · 2019-01-10 18:20

duedl0r's algorithm translated to 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))
}

worked example:

fib(4)
= fib(4, (0,1) )
= fib(3, (1,1) )
= fib(2, (1,2) )
= fib(1, (2,3) )
= 3
查看更多
男人必须洒脱
7楼-- · 2019-01-10 18:22

Say you want to have the the n'th fib number then build an array containing the preceeding numbers

int a[n];
a[0] = 0;
a[1] =1;
a[i] = n[i-1]+n[n-2];
查看更多
登录 后发表回答