Why is the complexity of computing the Fibonacci series 2n and not n2?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A common confusion is whether naive recursive Fibonacci runs in O(2^n) or O(n^2). The correct growth is exponential because recursion branches into two calls at most levels. Understanding the recursion tree makes the complexity argument straightforward.
Why Naive Recursion Grows Exponentially
The classic recursive function is F(n) = F(n-1) + F(n-2) with base cases for small n. Runtime follows a similar recurrence: T(n) = T(n-1) + T(n-2) + O(1).
That recurrence is dominated by Fibonacci growth itself, which is proportional to phi^n, where phi is approximately 1.618. Since phi^n is bounded above by 2^n, complexity is often written as O(2^n) for simplicity.
The repeated subproblem expansion is the root cause. For example, fib_naive(5) computes fib_naive(3) more than once.
Why It Is Not O(n^2)
O(n^2) suggests polynomial growth where doubling input roughly multiplies work by about four. Naive Fibonacci grows far faster: each increment in n adds a branching layer in the recursion tree.
You can observe this by counting function calls.
Call counts increase dramatically, demonstrating exponential behavior rather than polynomial growth.
Optimized Approaches and Their Complexities
Memoization stores computed values and turns recursion into linear-time dynamic programming. Iterative DP does the same with constant auxiliary space.
Complexities:
- Naive recursion: exponential, often written
O(2^n). - Memoized recursion:
O(n)time andO(n)space. - Iterative DP:
O(n)time andO(1)extra space.
Intuition You Can Reuse
Whenever recursion spawns multiple branches with overlapping subproblems and no caching, suspect exponential runtime. Whenever each state is solved once and reused, runtime often drops to linear or near-linear in number of states.
This reasoning pattern applies far beyond Fibonacci and is useful for many interview and production algorithm decisions.
Recurrence Intuition with the Call Tree
A call tree view makes complexity intuitive. At level zero, one call exists. At the next level, there are roughly two calls. At subsequent levels, branch count continues growing until base cases terminate recursion. Although branching is not perfectly full near leaves, total nodes still track Fibonacci growth closely. This growth rate is super-polynomial relative to n^2, which is why naive recursion becomes impractical quickly. For example, increasing n from 30 to 40 can multiply runtime by an order of magnitude, not by a small quadratic factor. When teaching complexity, pair recurrence equations with empirical call counts so the conceptual and observed behavior match. This dual perspective helps avoid memorized but misunderstood complexity claims.
Common Pitfalls
- Confusing recursive depth
nwith total number of recursive calls. - Assuming two recursive calls imply quadratic runtime automatically.
- Ignoring overlapping subproblems when analyzing recurrences.
- Benchmarking only tiny
nand drawing incorrect complexity conclusions.
Summary
- Naive Fibonacci recursion is exponential, commonly expressed as
O(2^n). - It is not quadratic because recursive call count grows much faster than
n^2. - Memoization converts repeated work into one-time state computation.
- Iterative DP provides linear time with constant extra space.
- Complexity analysis should focus on total work, not only recursion depth.

