The Fibonacci sequence is a sequence of numbers starting with 0 and 1 and then adding the sum of the two last numbers at the end of the sequence:

1
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The mathematical representation of the Fibonacci sequence is:

1
F(n) = F(n-1) + F(n-2)

Computing a Fibonacci sequence is one of the first things we learn while learning to program. A simple recursive implementation looks like this:

1
2
3
4
5
6
7
8
9
10
function fib(n) {
    switch(n) {
        case 0:
            return 0;
        case 1:
            return 1;
        default:
            return fib(n -1) + fib(n -2);
    }
}

Although this implementation is very straight forward it has two disadvantages: It’s time complexity is fib(n), which is very high for such a simple problem. Since it uses recursion there is a risk of running out of stack space.

We can improve the time complexity(from fib(n) to n) at the cost of n space complexity by using memoization:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function fib(n) {
    var cache = {};

    function calculate(n) {
        if (cache[n]) {
            return cache[n];
        }

        switch(n) {
            case 0:
                return 0;
            case 1:
                return 1;
            default:
                cache[n] = calculate(n - 1) + calculate(n - 2);
                return cache[n];
        }
    }

    return calculate(n);
}

A better approach is to use an iterative version with a time complexity of n and a constant space complexity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function fib(n) {
    if (n === 0) {
        return 0;
    }

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

    var secondLast = 0;
    var last = 1;
    var tmp;

    for (var i = 1; i < n; i++) {
        tmp = secondLast;
        secondLast = last;
        last = tmp + secondLast;
    }

    return last;
}

There are a couple more magical ways to get a Fibonacci number.

Fast doubling

This method is based on the fact that:

1
2
F(2n) = Fn(2F(n+1) - F(n))
F(2n + 1) = F(n+1)^2 + F(n)^2

The complexity of this algorithm is log n. Here is the implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function fib(n) {
    function fibTuple(n) {
        if (n <= 0) {
            return [0, 1];
        }
        var ab = fibTuple(Math.floor(n / 2));
        var a = ab[0], b = ab[1];
        var c = a * (2 * b - a);
        var d = b * b + a * a;
        if (n % 2 == 0) {
            return [c, d];
        } else {
            return [d, c + d];
        }
    }

    switch(n) {
        case 0:
            return 0;
        case 1:
            return 1;
        default:
            return fibTuple(n-1)[1];
    }
}

You can also get the Fibonacci number in constant time if you use rounding:

1
2
3
4
5
function fib(n) {
    var sqrt5 = Math.sqrt(5);
    var phi = (sqrt5 + 1) / 2;
    return Math.round(Math.pow(phi, n) / sqrt5);
}
[ computer_science  algorithms  javascript  programming  ]
B-Trees - Database storage internals
Programming Concurrency in Rust
Introduction to Rust
Introduction to HTML Canvas
React refs