509 - Fibonacci Number
Difficulty: Easy | Pattern: Recursion / DP / Math | Company tags: Amazon, Apple
Problem Statement
The Fibonacci numbers, commonly denoted F(n), form a sequence such that each number is the sum of the two preceding ones, starting from 0 and 1:
F(0) = 0, F(1) = 1
F(n) = F(n-1) + F(n-2) for n > 1
Given n, calculate F(n).
Example 1: F(2) = 1 (0, 1, 1)
Example 2: F(3) = 2 (0, 1, 1, 2)
Example 3: F(4) = 3 (0, 1, 1, 2, 3)
Constraints: 0 <= n <= 30
Four Approaches (from Slow to Fast)
Approach 1: Naive Recursion — O(2^n) time (exponential, DO NOT USE)
def fib(n: int) -> int:
if n <= 1:
return n
return fib(n-1) + fib(n-2)
Problem: Exponential time — recomputes the same subproblems. fib(40) makes ~2 billion calls.
Approach 2: Memoization (Top-Down DP) — O(n) time, O(n) space
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n: int) -> int:
if n <= 1:
return n
return fib(n-1) + fib(n-2)
Or manually:
def fib(n: int) -> int:
memo = {}
def helper(k):
if k <= 1:
return k
if k not in memo:
memo[k] = helper(k-1) + helper(k-2)
return memo[k]
return helper(n)
Approach 3: Bottom-Up DP — O(n) time, O(n) space
def fib(n: int) -> int:
if n <= 1:
return n
dp = [0] * (n + 1)
dp[1] = 1
for i in range(2, n + 1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
Approach 4: Space-Optimized DP — O(n) time, O(1) space
def fib(n: int) -> int:
if n <= 1:
return n
prev, curr = 0, 1
for _ in range(2, n + 1):
prev, curr = curr, prev + curr
return curr
This is the best solution — O(n) time, O(1) space.
Algorithm Flow
Complexity Comparison
| Approach | Time | Space |
|---|---|---|
| Naive recursion | O(2^n) | O(n) call stack |
| Memoization | O(n) | O(n) |
| Bottom-up DP | O(n) | O(n) |
| Space-optimized | O(n) | O(1) |
Teaching Value
This problem introduces three fundamental DP concepts:
- Overlapping subproblems: The same sub-problem is computed multiple times in naive recursion
- Memoization: Cache results to avoid recomputation (top-down)
- Tabulation: Build up from base cases (bottom-up) — often simpler to reason about
Key Terms
| Term | Definition |
|---|---|
| Overlapping subproblems | The same smaller input recurs many times during recursion, making naive recomputation wasteful. |
| Memoization | Top-down caching of subproblem results (e.g. via lru_cache or a dict) so each value is computed once. |
| Tabulation | Bottom-up DP that fills an array from base cases upward, avoiding recursion overhead entirely. |
| Space optimization | Reducing an O(n) DP array to O(1) by keeping only the last two states needed for the next computation. |
FAQ
- Can this be solved without extra space? Yes — the space-optimized iterative version keeps only
prevandcurr, achieving O(1) space and O(n) time. - What if n is 0?
F(0) = 0by definition; the base-case checkif n <= 1: return nhandles it directly. - How would this change if n could be very large (e.g. n = 10^9)? Iterative O(n) would be too slow; you'd use matrix exponentiation on
[[1,1],[1,0]]or Binet's formula for O(log n) time. - Why avoid naive recursion in an interview even though it's "correct"? It's exponential — O(2^n) — because it recomputes the same subproblems repeatedly, which is precisely the motivation for introducing memoization.
- Is memoization or tabulation preferred here? For this problem, space-optimized iteration is best overall; between the two DP styles, tabulation avoids recursion/call-stack overhead, while memoization is more natural when the recursion tree is irregular.
Quick Revision
- Problem: compute the nth Fibonacci number,
F(n) = F(n-1) + F(n-2),F(0)=0, F(1)=1. - Naive recursion is O(2^n) — recomputes overlapping subproblems, avoid in interviews.
- Memoization (top-down): cache each
fib(k)the first time it's computed — O(n) time, O(n) space. - Tabulation (bottom-up): fill a
dparray from base cases upward — O(n) time, O(n) space. - Space-optimized: track only
prevandcurr, update in a loop — O(n) time, O(1) space (best answer). - This problem is the canonical teaching example for overlapping subproblems and DP.
- For very large n, matrix exponentiation gives O(log n) time.
- Always state the space-optimized version as your final answer unless asked for alternatives.
Related Problems
- Same DP-on-a-line pattern: 746 - Min Cost Climbing Stairs
- Same DP progression style (recursion to space-optimized): 256 - Paint House