Step 1: Call fib(4), check memo (empty), compute fib(3) and fib(2)
memo: {}
fib(4) waits for fib(3) and fib(2)Why: We need fib(3) and fib(2) to find fib(4)
Step 2: Call fib(3), check memo (empty), compute fib(2) and fib(1)
memo: {}
fib(3) waits for fib(2) and fib(1)Why: fib(3) depends on fib(2) and fib(1)
Step 3: Call fib(2), check memo (empty), compute fib(1) and fib(0)
memo: {}
fib(2) waits for fib(1) and fib(0)Why: fib(2) depends on fib(1) and fib(0)
Step 4: fib(1) and fib(0) are base cases, return 1 and 0, store in memo
memo: {1:1, 0:0}
fib(2) can now computeWhy: Base cases give known answers
Step 5: Compute fib(2) = fib(1)+fib(0) = 1+0=1, store in memo
memo: {1:1, 0:0, 2:1}
fib(3) waits for fib(1)Why: fib(2) result saved to avoid recomputation
Step 6: fib(1) found in memo, return 1 immediately
memo: {1:1, 0:0, 2:1}
fib(3) can now computeWhy: Memoization avoids repeated work
Step 7: Compute fib(3) = fib(2)+fib(1) = 1+1=2, store in memo
memo: {1:1, 0:0, 2:1, 3:2}
fib(4) waits for fib(2)Step 8: fib(2) found in memo, return 1 immediately
memo: {1:1, 0:0, 2:1, 3:2}
fib(4) can now computeWhy: Memoization saves time
Step 9: Compute fib(4) = fib(3)+fib(2) = 2+1=3, store in memo
memo: {1:1, 0:0, 2:1, 3:2, 4:3}
Result fib(4) = 3Why: Final answer computed efficiently
Result: memo: {0:0, 1:1, 2:1, 3:2, 4:3}
Fib(4) = 3