The definition gives the answer directly: each Fibonacci number is the sum of the two before it. The challenge is not figuring out what to compute, but how to compute it efficiently.
A recursive implementation that mirrors the definition recalculates the same subproblems repeatedly. Computing F(5) requires F(4) and F(3), but computing F(4) also requires F(3), so F(3) is computed twice. As n grows, this redundancy grows exponentially. Eliminating it is the entire point of the problem, and Fibonacci is the standard introduction to dynamic programming.
0 <= n <= 30 → The largest answer is F(30) = 832,040, which fits comfortably in a 32-bit integer, so overflow is not a concern. The small upper bound on n means even the exponential brute force runs in well under a second, but it still does roughly 2.7 million calls for n=30 against only 31 distinct subproblems, which motivates caching.Translate the mathematical definition into code: F(n) calls F(n-1) and F(n-2), each of which makes its own recursive calls, down to the base cases F(0) = 0 and F(1) = 1.
This is correct but inefficient. The recursion tree branches in two at every level, and the same subproblems are solved repeatedly. Computing F(5) computes F(3) twice, F(2) three times, and F(1) five times. The total number of calls grows exponentially with n.
n <= 1, return n (base cases: F(0) = 0, F(1) = 1).fib(n - 1) + fib(n - 2).Let's trace through n = 4:
The exponential time comes from recomputing the same subproblems. For F(30), the recursion makes about 2.7 million calls, but there are only 31 distinct subproblems. Storing each result the first time it is computed removes the redundancy entirely.
The recursive approach solves only a handful of distinct subproblems but solves them many times over. Caching the result of each F(k) lets every later call return it in O(1) instead of recomputing the entire subtree.
This technique is called memoization. It keeps the top-down recursive structure but computes each F(k) at most once: the first call stores the result, and every subsequent call reads it back.
n <= 1, return n.memo[n] is already computed (not -1), return it.fib(n - 1) + fib(n - 2), store it in memo[n], and return it.Computing the next Fibonacci number requires only the two most recent ones, so storing all n+1 values is unnecessary. The next approach builds up from the base cases while keeping only the last two values.
Instead of recursing top-down, build the sequence bottom-up. Start from F(0) = 0 and F(1) = 1, then compute F(2), F(3), ..., F(n) in order. Each step needs only the previous two values, so two variables suffice.
This removes both the recursion overhead and the memo array, giving O(n) time and O(1) extra space.
n <= 1, return n.prev2 = 0 (F(0)) and prev1 = 1 (F(1)).i = 2 to n:current = prev1 + prev2.prev2 = prev1, prev1 = current.prev1.The O(n) iterative solution is the answer for this problem's constraints. The next approach reaches the answer in O(log n) time, which matters when n is large enough that a linear scan is the bottleneck.
The recurrence F(n) = F(n-1) + F(n-2) can be written as a single matrix multiplication. If we treat the pair of consecutive Fibonacci numbers as a column vector, then
Applying this transformation repeatedly gives a closed form. Let M = [[1, 1], [1, 0]]. Raising M to the power n produces the Fibonacci numbers directly:
So F(n) is the top-right entry of M^n. Computing M^n by multiplying M by itself n times would still be O(n), but matrix powers can be computed with fast exponentiation (exponentiation by squaring): M^n is built by repeatedly squaring, which takes only O(log n) matrix multiplications.
n <= 1, return n.M = [[1, 1], [1, 0]].[0][1] of the accumulated matrix. Return that entry.Because each 2x2 multiply is constant work and the exponent halves each iteration, the total cost is O(log n).
The result matrix is shown flattened as [a, b, c, d] for [[a, b], [c, d]]. After processing all bits of the exponent 6, the result holds M^6 = [[13, 8], [8, 5]], and index [0][1] is 8, which is F(6).
For this problem the O(n) iterative solution is already fast enough, and it is simpler to write correctly. The matrix method is the standard way to evaluate Fibonacci when n is large (for example, computing F(n) mod a prime for n in the billions), where O(log n) is the difference between feasible and not.