15% off all plans & roadmaps Use code
See plansEditorial
Core insight
Fibonacci Number · Dynamic Programming (DP) Patterns
Core Insight for Fibonacci Number
The core insight needed to move from the brute force approach to the optimal solution is the recognition of overlapping subproblems. In the recursion tree, the value of fib(k) is computed repeatedly for the same k.
By applying the Dynamic Programming pattern, we can eliminate this redundancy. Instead of starting from and working backward (Top-Down), we start from the base cases ( and ) and work forward (Bottom-Up).
Visual Description: Imagine a linear array of size . We know the values at index 0 and index 1. To fill index 2, we simply look at the values at indices 0 and 1. To fill index 3, we look at indices 1 and 2. The dependency graph is a simple straight line where node depends only on and . Since we process in increasing order, the values needed for the current step are always available and already computed.
Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 509: Fibonacci Number Solution & Explanation
Problem Overview
TL;DR: The optimal solution uses an iterative bottom-up approach (Dynamic Programming) to calculate the -th value by summing the two previous values, reducing the time complexity to linear and space to constant.
The Fibonacci Number problem asks us to compute the -th term in the Fibonacci sequence. The sequence is defined recursively where each number is the sum of the two preceding ones. Specifically, , , and for any , . While the mathematical definition is recursive, LeetCode 509 serves as a fundamental introduction to optimizing recursive problems using Dynamic Programming.
Brute Force Approach for Fibonacci Number
The most intuitive way to solve the Fibonacci Number problem is to directly translate the mathematical recurrence relation into code using recursion.
The algorithm functions as follows:
- Check if is 0 or 1. If so, return .
- Otherwise, recursively call the function for and and return their sum.
1# Pseudo-code for Brute Force
2function fib(n):
3 if n <= 1:
4 return n
5 return fib(n - 1) + fib(n - 2)Why this approach fails: The time complexity of this recursive solution is . This exponential growth occurs because the algorithm re-calculates the same subproblems multiple times. For example, to calculate , it calculates and . However, the calculation of also calculates . As increases, the number of redundant operations explodes, leading to a Time Limit Exceeded (TLE) on larger constraints or significant inefficiency on moderate ones.
Algorithm Strategy: Dynamic Programming (DP) Patterns
The strategy utilizes the DP - 1D Array subpattern with a space optimization.
- State Definition: Let
dp[i]represent the -th Fibonacci number. - Recurrence Relation:
dp[i] = dp[i-1] + dp[i-2]. - Base Cases:
dp[0] = 0,dp[1] = 1. - Space Optimization: Notice that to calculate
dp[i], we only needdp[i-1]anddp[i-2]. We do not need to accessdp[i-3]or any earlier values. Therefore, we do not need to maintain the entire array in memory. We can maintain just two variables,prev2(representing ) andprev1(representing ), and update them iteratively.
This transforms the space complexity from (using an array) to (using variables), which is the optimal solution for interviews.
Execution Flow
- Handle Base Cases: If , return 0. If , return 1.
- Initialize State:
- Set
prev2 = 0(corresponds to ). - Set
prev1 = 1(corresponds to ).
- Set
- Iterate: Loop from up to .
- Calculate
current = prev1 + prev2. - Update pointers for the next iteration:
prev2becomes the oldprev1.prev1becomes the calculatedcurrent.
- Calculate
- Return Result: After the loop finishes,
prev1holds the value of .
Proof of Correctness
The correctness is proven via mathematical induction.
- Base Case: The algorithm explicitly handles or initializes correctly for and .
- Inductive Step: Assume that at iteration ,
prev1correctly holds andprev2correctly holds . The algorithm computescurrent = prev1 + prev2, which is . By the definition of the Fibonacci sequence, this sum is exactly . - Termination: The loop terminates at , ensuring the final value stored in
prev1is .
Pattern Reuse Notes
The DP - 1D Array (Fibonacci Style) pattern is foundational. The logic of depending on the previous one or two states applies directly to:
- LeetCode 70: Climbing Stairs (Identical recurrence: )
- LeetCode 91: Decode Ways (Conditional recurrence based on previous 1 or 2 digits)
- LeetCode 198: House Robber (Choice between robbing current house + vs skipping current house + )
- LeetCode 213: House Robber II (Same logic as House Robber, with circular array handling)
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 509
1class Solution {
2public:
3 int fib(int n) {
4 // Base cases
5 if (n == 0) return 0;
6 if (n == 1) return 1;
7
8 // DP state variables
9 int prev2 = 0; // F(0)
10 int prev1 = 1; // F(1)
11
12 // Iterative Bottom-Up Calculation
13 for (int i = 2; i <= n; ++i) {
14 int current = prev1 + prev2;
15 prev2 = prev1;
16 prev1 = current;
17 }
18
19 return prev1;
20 }
21};Java Solution for LeetCode 509
1class Solution {
2 public int fib(int n) {
3 // Base cases
4 if (n == 0) return 0;
5 if (n == 1) return 1;
6
7 // DP state variables
8 int prev2 = 0; // F(0)
9 int prev1 = 1; // F(1)
10
11 // Iterative Bottom-Up Calculation
12 for (int i = 2; i <= n; i++) {
13 int current = prev1 + prev2;
14 prev2 = prev1;
15 prev1 = current;
16 }
17
18 return prev1;
19 }
20}Python Solution for LeetCode 509
1class Solution:
2 def fib(self, n: int) -> int:
3 # Base cases
4 if n == 0:
5 return 0
6 if n == 1:
7 return 1
8
9 # DP state variables
10 prev2, prev1 = 0, 1
11
12 # Iterative Bottom-Up Calculation
13 for _ in range(2, n + 1):
14 current = prev1 + prev2
15 prev2 = prev1
16 prev1 = current
17
18 return prev1