Making Fibonacci faster
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The Fibonacci sequence (0, 1, 1, 2, 3, 5, 8, 13, ...) where F(n) = F(n-1) + F(n-2) is a classic problem for exploring algorithmic optimization. The naive recursive solution has exponential time complexity O(2^n), making it impractical for even moderately large inputs. Several techniques — memoization, bottom-up iteration, matrix exponentiation, and closed-form formulas — dramatically improve performance from exponential down to O(n) or even O(log n).
Method 1: Naive Recursion — O(2^n)
The direct translation of the mathematical definition:
The problem: fib_naive(5) computes fib(3) twice, fib(2) three times, and fib(1) five times. The number of function calls grows exponentially.
Method 2: Memoization (Top-Down DP) — O(n)
Cache previously computed results:
Time: O(n). Space: O(n) for the cache and recursion stack.
Method 3: Bottom-Up Iteration — O(n)
Build the sequence from the bottom, using constant space:
Time: O(n). Space: O(1). This is the most practical solution for most use cases — no recursion stack, no cache overhead.
Method 4: Matrix Exponentiation — O(log n)
The Fibonacci recurrence can be expressed as matrix multiplication:
Using fast matrix exponentiation (repeated squaring), this computes F(n) in O(log n) multiplications:
Time: O(log n) matrix multiplications. Each multiplication involves constant (2x2) matrices, but the numbers themselves grow exponentially, so arithmetic on large numbers adds overhead.
Method 5: Fast Doubling — O(log n)
An optimization of matrix exponentiation using the identities:
- F(2k) = F(k) * [2*F(k+1) - F(k)]
- F(2k+1) = F(k)^2 + F(k+1)^2
This is the fastest practical algorithm — it avoids matrix multiplication overhead while maintaining O(log n) recursive calls.
Method 6: Binet's Formula (Closed-Form) — O(1)
The golden ratio formula gives F(n) directly:
Time: O(1). But floating-point precision limits this to approximately n < 75. For larger values, use integer-based methods.
Comparison
| Method | Time | Space | Practical limit |
| Naive recursion | O(2^n) | O(n) stack | n ~ 35 |
| Memoization | O(n) | O(n) | n ~ 1000 (recursion limit) |
| Iteration | O(n) | O(1) | n ~ 10^7 |
| Matrix exponentiation | O(log n) | O(log n) stack | n ~ 10^9 |
| Fast doubling | O(log n) | O(log n) stack | n ~ 10^9 |
| Binet's formula | O(1) | O(1) | n ~ 75 (precision limit) |
Language-Specific Implementations
C++ (Iterative)
JavaScript
Common Pitfalls
- Recursion depth limit: Python's default recursion limit is 1000.
fib_memo(1500)raisesRecursionError. Increase withsys.setrecursionlimit(10000)or use iterative/fast-doubling methods. - Integer overflow: In C/C++/Java,
long longoverflows at F(92) = 7,540,113,804,746,346,429. Use arbitrary-precision libraries (BigIntegerin Java,__int128in C++) for larger values. - Floating-point errors in Binet's formula:
math.sqrt(5)has limited precision. F(72) computed with Binet's formula is already off by 1. Only use for small n or as an approximation. - Memoization cache size:
@lru_cache(maxsize=None)stores all computed values forever. For very large n, this uses significant memory. Clear withfib_memo.cache_clear()or use iterative methods. - Off-by-one errors: Some implementations define F(0)=0, F(1)=1 while others define F(1)=1, F(2)=1. Be consistent and document your convention.
Summary
- Use iterative bottom-up (O(n), O(1) space) for most practical applications
- Use fast doubling (O(log n)) for very large Fibonacci numbers (F(1,000,000)+)
- Use
@lru_cachememoization for the simplest code with O(n) time - Avoid naive recursion — it is exponential and unusable beyond n ~ 35
- Avoid Binet's formula for n > 70 due to floating-point precision limits

