Memoization to Optimize Recursion in DSA C# - Time & Space Complexity
We want to see how adding memoization changes the speed of a recursive function.
How does remembering past answers help us do less work?
Analyze the time complexity of the following code snippet.
public int Fibonacci(int n, Dictionary<int, int> memo)
{
if (n <= 1) return n;
if (memo.ContainsKey(n)) return memo[n];
memo[n] = Fibonacci(n - 1, memo) + Fibonacci(n - 2, memo);
return memo[n];
}
This code calculates the nth Fibonacci number using recursion with memoization to store results.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls to Fibonacci with smaller n.
- How many times: Each unique n is computed once and then reused from memo.
Each number from 0 up to n is calculated once, then reused.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 calculations |
| 100 | About 100 calculations |
| 1000 | About 1000 calculations |
Pattern observation: The work grows roughly in a straight line as n grows.
Time Complexity: O(n)
This means the function does work proportional to n, much faster than without memoization.
[X] Wrong: "Recursion with memoization still does all calls like normal recursion."
[OK] Correct: Memoization saves results so repeated calls don't redo work, cutting down the total calls drastically.
Understanding how memoization changes recursion speed shows you can improve slow code by remembering past answers, a key skill in problem solving.
"What if we removed the memo dictionary? How would the time complexity change?"
Practice
memoization in recursive functions?Solution
Step 1: Understand recursion inefficiency
Recursive functions often repeat the same calculations multiple times, which wastes time.Step 2: Role of memoization
Memoization saves the results of these repeated calculations so they can be reused instead of recalculated.Final Answer:
To store results of expensive function calls and reuse them -> Option DQuick Check:
Memoization = Store and reuse results [OK]
- Thinking memoization slows down recursion
- Confusing memoization with iteration
- Believing memoization removes recursion
Solution
Step 1: Identify correct generic dictionary syntax
In C#, a dictionary with integer keys and values is declared as Dictionary.Step 2: Check options for correct syntax
Dictionary memo = new Dictionary(); uses Dictionary with proper initialization, others use wrong types or missing generics.Final Answer:
Dictionary memo = new Dictionary(); -> Option CQuick Check:
Dictionary = Correct memo declaration [OK]
- Using List or HashSet instead of Dictionary
- Missing generic type parameters
- Using untyped Dictionary without generics
using System;
using System.Collections.Generic;
class Program {
static Dictionary memo = new Dictionary();
static int Fib(int n) {
if (n <= 1) return n;
if (memo.ContainsKey(n)) return memo[n];
memo[n] = Fib(n - 1) + Fib(n - 2);
return memo[n];
}
static void Main() {
Console.WriteLine(Fib(5));
}
}Solution
Step 1: Understand Fibonacci calculation
Fib(5) = Fib(4) + Fib(3). Calculating recursively with memoization avoids repeated work.Step 2: Calculate Fib(5) step-by-step
Fib(0)=0, Fib(1)=1, Fib(2)=1, Fib(3)=2, Fib(4)=3, Fib(5)=5.Final Answer:
5 -> Option AQuick Check:
Fib(5) = 5 [OK]
- Confusing Fib(5) with Fib(6)
- Ignoring memoization effect
- Miscounting base cases
static Dictionary memo = new Dictionary();
static int Factorial(int n) {
if (n == 0) return 1;
if (memo.ContainsKey(n)) return memo[n];
memo[n] = n * Factorial(n - 1);
return n;
}Solution
Step 1: Analyze return statement after recursion
The function returns 'n' instead of the computed factorial stored in memo[n], which is incorrect.Step 2: Correct return value
Return memo[n] to return the calculated factorial value after storing it.Final Answer:
Return memo[n] instead of n after recursive call -> Option BQuick Check:
Return memo[n] fixes incorrect output [OK]
- Returning input parameter instead of memoized result
- Changing base case unnecessarily
- Misusing memo dictionary keys
n stairs taking 1 or 2 steps at a time. Which memoization approach below correctly implements this in C#?Solution
Step 1: Understand problem and base cases
Number of ways to climb stairs with 1 or 2 steps: ways(0)=1 (one way to stand still), ways(1)=1.Step 2: Correct memoization approach
Use Dictionary to store results; recursive call sums ways(n-1) and ways(n-2) to count all paths.Final Answer:
Use a Dictionary to store results; base cases for 0 and 1 stairs return 1; recursive call sums ways(n-1) and ways(n-2). -> Option AQuick Check:
Memo + base cases + sum recursion = Use a Dictionary to store results; base cases for 0 and 1 stairs return 1; recursive call sums ways(n-1) and ways(n-2). [OK]
- Wrong base cases values
- Using multiplication instead of addition
- Missing base cases causing infinite recursion
Ready to prove it?
Pass the test and this pattern moves unknown
