Fibonacci Using DP in DSA Python - Time & Space Complexity
We want to know how fast the Fibonacci numbers can be calculated using dynamic programming.
How does the time needed grow as the input number gets bigger?
Analyze the time complexity of the following code snippet.
def fibonacci_dp(n):
fib = [0, 1]
for i in range(2, n + 1):
fib.append(fib[i - 1] + fib[i - 2])
return fib[n]
This code calculates the nth Fibonacci number by building up from the bottom using a list to store results.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that adds two previous Fibonacci numbers to get the next one.
- How many times: It runs once for each number from 2 up to n, so about n-1 times.
Each new Fibonacci number is found by adding two earlier numbers once, so the work grows steadily with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 9 additions |
| 100 | About 99 additions |
| 1000 | About 999 additions |
Pattern observation: The number of operations grows roughly in a straight line as n increases.
Time Complexity: O(n)
This means the time to find the nth Fibonacci number grows directly with n, so doubling n roughly doubles the work.
[X] Wrong: "Calculating Fibonacci with recursion is always fast because it just calls itself."
[OK] Correct: Simple recursion repeats many calculations, making it much slower than this dynamic programming approach.
Understanding how dynamic programming improves speed by remembering past results is a key skill that shows you can write efficient code.
"What if we used recursion with memoization instead of a loop? How would the time complexity change?"
Practice
Solution
Step 1: Understand recursive Fibonacci inefficiency
Simple recursion recalculates the same Fibonacci numbers many times, causing exponential time complexity.Step 2: How DP improves calculation
DP stores previously calculated Fibonacci numbers in a table (memoization or tabulation), avoiding repeated work.Final Answer:
It avoids repeated calculations by storing intermediate results. -> Option AQuick Check:
DP stores results to avoid repeats [OK]
- Thinking DP uses less memory than recursion
- Believing DP removes addition operations
- Confusing DP with randomization
Solution
Step 1: Determine list size for Fibonacci DP
For n=5, we need indices 0 to 5 inclusive, so list size must be 6.Step 2: Check initialization correctness
fib = [0] * 6 creates a list of six zeros, ready to store fib[0] to fib[5].Final Answer:
fib = [0] * 6 -> Option BQuick Check:
List size = n+1 for fib numbers [OK]
- Using list size equal to n instead of n+1
- Initializing with ones instead of zeros
- Leaving list empty without size
def fib_dp(n):
fib = [0] * (n+1)
fib[0], fib[1] = 0, 1
for i in range(2, n+1):
fib[i] = fib[i-1] + fib[i-2]
return fib[n]
print(fib_dp(6))Solution
Step 1: Trace Fibonacci values up to n=6
fib[0]=0, fib[1]=1; then fib[2]=1, fib[3]=2, fib[4]=3, fib[5]=5, fib[6]=8.Step 2: Return fib[6]
The function returns fib[6], which is 8.Final Answer:
8 -> Option CQuick Check:
fib(6) = 8 [OK]
- Confusing fib(6) with fib(7)
- Starting fib from 1 instead of 0
- Off-by-one errors in loop range
def fib_dp(n):
fib = [0] * n
fib[0], fib[1] = 0, 1
for i in range(2, n+1):
fib[i] = fib[i-1] + fib[i-2]
return fib[n]Solution
Step 1: Check list size for indexing
fib list size is n, but code accesses fib[n], which is out of range.Step 2: Fix list size
Changing fib = [0] * n to fib = [0] * (n+1) allows indexing up to fib[n].Final Answer:
Change fib = [0] * n to fib = [0] * (n+1) -> Option DQuick Check:
List size must cover fib[n] index [OK]
- Not increasing list size causes IndexError
- Changing base cases incorrectly
- Altering loop range wrongly
def fib_sum(n):
fib = [0] * (n+1)
fib[0], fib[1] = 0, 1
for i in range(2, n+1):
fib[i] = fib[i-1] + fib[i-2]
# What to add here to get sum of fib[0] to fib[n]?
return ???Solution
Step 1: Understand sum of Fibonacci numbers
The sum of first n Fibonacci numbers is fib[0] + fib[1] + ... + fib[n].Step 2: Use known Fibonacci sum formula
The sum of first n Fibonacci numbers equals fib[n+2] - 1.Final Answer:
return fib[n+2] - 1 -> Option AQuick Check:
Sum of fib numbers = fib[n+2] - 1 [OK]
- Using fib[n]*2 which is incorrect
- Using sum(fib) which is inefficient
- Adding only last two fib numbers
Ready to prove it?
Pass the test and this pattern moves unknown
