Chapter 51

Home

Fibonacci with DP

You've seen naive Fibonacci (O(2ᴺ)) and memoised Fibonacci (O(N)). Now see all three approaches side by side, plus the bottom-up tabulation version. This is your template for every DP problem.

Three Approaches to Fibonacci

C++ — naive (O(2ᴺ)) — don't use

int fib(int n) {
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}

C++ — top-down memoisation (O(N))

vector memo(N + 1, -1);

int fib(int n) {
    if (n <= 1) return n;
    if (memo[n] != -1) return memo[n];
    return memo[n] = fib(n - 1) + fib(n - 2);
}

C++ — bottom-up tabulation (O(N))

int fib(int n) {
    if (n <= 1) return n;
    vector dp(n + 1);
    dp[0] = 0; dp[1] = 1;
    for (int i = 2; i <= n; i++)
        dp[i] = dp[i - 1] + dp[i - 2];
    return dp[n];
}

Rust — bottom-up tabulation

fn fib(n: usize) -> u64 {
    if n <= 1 { return n as u64; }
    let mut dp = vec![0u64; n + 1];
    dp[0] = 0; dp[1] = 1;
    for i in 2..=n {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    dp[n]
}

💡 Tabulation always wins for Fibonacci

No recursion overhead, no cache-miss checking, no stack depth limit. Bottom-up is faster in practice for linear DP like Fibonacci. Top-down memoisation shines when the dependency graph is complex and you'd compute many unused states.

Key Takeaways

Practice