Making Fibonacci faster
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
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
Related reading
- making generic algorithms in go
- Manacher's algorithm algorithm to find longest palindrome substring in linear time
- Map Clustering Algorithm
- Map incrementing integer range to six-digit base 26 max, but unpredictably
- Making sure (distributed) caches only store the latest value in a distributed system
- Making the Android emulator run faster
- Map Tiling Algorithm
- Mapping N-dimensional value to a point on Hilbert curve

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.