I know that:
int fib(int n)
{
if (n == 0 || n == 1)
return 1;
return fib(n − 1)+ fib(n − 2);
}
when n=5,fib(5) evaluates as:
fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
Notice that each base element being used for several times, is there a way to use map to store the previous value and simply do fib(n − 1) + fib(n − 2)?
Efficient Fibonacci Series solution with dynamic programming.
Of course you can!
Very basic example in python:
In C++, the two solutions at your disposal that would save you time are the dynamic programming approach and the memoization approach.
Dynamic Programming
We just build a table from
[1..n]
and fill it in:Memoization
Here, we implement
fib
as normal, but save off the intermediate steps:The more standard approach to memoization would involve a hash-table on the inputs - but in this case since we know that to compute
fib(n)
we also needfib(1)
thrufib(n-1)
, avector
would be more efficient. Or do we?Sublinear
We don't actually have to compute
fib(1)
thrufib(n-1)
to getfib(n)
. We could do it directly:Because math is cool.
Yes. The primitive recursive solution takes a lot of time. The reason for this is that for each number calculated, it needs to calculate all the previous numbers more than once.
What makes it even worse is that with each fibonacci number you calculate in your list, you don't use the previous numbers you have knowledge of to speed up the computation – you compute each number "from scratch."
There are a few options to make this faster:
1. Create a list "from the bottom up"
The easiest way is to just create a list of fibonacci numbers up to the number you want. If you do that, you build "from the bottom up" or so to speak, and you can reuse previous numbers to create the next one. If you have a list of the fibonacci numbers
[0, 1, 1, 2, 3]
, you can use the last two numbers in that list to create the next number.This approach would look something like this:
Then you can get the first 20 fibonacci numbers by doing
Or you can get the 17th fibonacci number from a list of the first 40 by doing
2. Memoization (relatively advanced technique)
Another alternative to make it faster exists, but it is a little more complicated as well. Since your problem is that you re-compute values you have already computed, you can instead choose to save the values you have already computed in a dict, and try to get them from that before you recompute them. This is called memoization. It may look something like this:
This allows you to compute big fibonacci numbers in a breeze:
This is in fact such a common technique that Python 3 includes a decorator to do this for you. I present to you, automatic memoization!
This does pretty much the same thing as the previous function, but with all the
computed
stuff handled by thelru_cache
decorator.3. Just count up (a naïve iterative solution)
A third method, as suggested by Mitch, is to just count up without saving the intermediary values in a list. You could imagine doing
I don't recommend these last two methods if your goal is to create a list of fibonacci numbers.
fib_to(100)
is going to be a lot faster than[fib(n) for n in range(101)]
because with the latter, you still get the problem of computing each number in the list from scratch.Checkout this for different algorithms: http://www.nayuki.io/page/fast-fibonacci-algorithms
Credits: kqr