CMD Guide
HomeDSADynamic Programming

Fibonacci numbers

Fibonacci is the canonical DP warm-up because it exposes the exact mechanism every DP problem exploits: a state (n) whose answer depends on two smaller instances of the same subproblem, and those subproblems overlap massively as recursion unwinds — so caching (or building bottom-up) collapses exponential work into linear work.

Recognize the pattern

Brute force → optimal

Brute force (naive recursion): directly translate the recurrence into a function that calls itself twice per level, with no memory of past calls.

static long fibNaive(int n) {
    if (n <= 1) return n;
    return fibNaive(n - 1) + fibNaive(n - 2);
}

This rebuilds the entire call tree every time a subproblem recurs, costing exponential time and O(n) space just for the recursion stack.

Optimal (bottom-up tabulation, rolling variables): observe that computing f(n) only ever needs the last two values, so iterate forward and keep two running variables instead of a tree or even a full array.

static long fibDP(int n) {
    if (n <= 1) return n;
    long prev2 = 0, prev1 = 1;
    for (int i = 2; i <= n; i++) {
        long curr = prev1 + prev2;
        prev2 = prev1;
        prev1 = curr;
    }
    return prev1;
}

Complexity, derived

Naive recursion: let T(n) be the number of calls to compute f(n). T(n) = T(n-1) + T(n-2) + 1, with T(0)=T(1)=1. This is itself Fibonacci-shaped, and since consecutive Fibonacci ratios converge to φ ≈ 1.618, T(n) grows as Θ(φⁿ) — exponential time. Space is O(n) for the deepest recursion stack (the chain of pending f(n-1) calls).

Bottom-up: the loop body does a fixed number of operations (one add, two assignments) and runs exactly n-1 times → Θ(n) time. Only two scalars are kept alive at once → O(1) auxiliary space (a full memo array would be O(n) space instead).

Traced example: fib(6)

iprev2prev1curr = prev1+prev2
start01-
2011
3112
4123
5235
6358

Result: fib(6) = 8, matching 0,1,1,2,3,5,8. Each row overwrites prev2/prev1 rather than growing a table.

Pitfalls

When to use / when not — trade-offs

Rolling-variable bottom-up (this page): use whenever only the last k states are needed and you want a single final answer — O(n) time, O(1) space, no recursion overhead.

vs. Top-down memoization: easier to write when the recursion is irregular or has many branches (e.g., not a clean linear chain), and it computes only the states actually needed rather than all of 0..n; but it costs O(n) stack space and function-call overhead vs. tight loop iterations.

vs. Matrix exponentiation / fast doubling: use when n is huge (n ~ 10^9 or more) and only the final value is needed — O(log n) time by repeated squaring of the transformation matrix [[1,1],[1,0]]; not worth the complexity for small, bounded n like this problem's n ≤ 30.

vs. Closed-form (Binet's formula): O(1) time using powers of the golden ratio, but suffers floating-point precision loss for larger n — unreliable for exact integer answers beyond small n.

Takeaways

Recall: Why does naive recursive Fibonacci take exponential time, and what single change makes it linear?


Source: adapted from standard interview-prep Fibonacci problem statement and standard dynamic-programming derivations.

🤖 Don't fully get this? Learn it with Claude

Stuck on Fibonacci numbers? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Fibonacci numbers** (DSA) and want to truly understand it. Explain Fibonacci numbers from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Fibonacci numbers** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Fibonacci numbers** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Fibonacci numbers** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes