Recursion is a method where a function calls itself to solve smaller parts of a problem until it reaches a simple base case.
Click to reveal answer
intermediate
What does DP (Dynamic Programming) do differently from simple recursion?
DP stores results of solved subproblems to avoid repeating work, making it faster than simple recursion for overlapping problems.
Click to reveal answer
beginner
When is a greedy algorithm the right choice?
Greedy algorithms work well when choosing the best option at each step leads to a global best solution, without needing to reconsider choices.
Click to reveal answer
beginner
Why might recursion be inefficient for some problems?
Recursion can be inefficient if it solves the same subproblems many times, causing repeated work and slow performance.
Click to reveal answer
intermediate
How do you decide between DP and greedy approaches?
Use DP when subproblems overlap and you need to remember past results; use greedy when local best choices lead to a global best solution.
Click to reveal answer
Which approach stores results of subproblems to avoid repeated work?
AGreedy Algorithm
BBrute Force
CSimple Recursion
DDynamic Programming
✗ Incorrect
Dynamic Programming saves results of subproblems to improve efficiency.
When is a greedy algorithm most suitable?
AWhen local choices lead to global optimum
BWhen recursion depth is large
CWhen subproblems overlap
DWhen all solutions must be checked
✗ Incorrect
Greedy algorithms work best when local best choices lead to the overall best solution.
What is a main drawback of simple recursion without optimization?
ARepeats solving the same subproblems
BUses too much memory
CAlways slower than greedy
DCannot solve problems with base cases
✗ Incorrect
Simple recursion can repeat work by solving the same subproblems multiple times.
Which method is best if you need to explore all possible solutions?
AGreedy Algorithm
BDynamic Programming
CRecursion or Backtracking
DSorting
✗ Incorrect
Recursion or backtracking explores all possibilities, useful when greedy or DP don't apply.
What is a key sign to use DP over recursion?
ANo overlapping subproblems
BOverlapping subproblems and optimal substructure
CProblem requires only one pass
DProblem is unsolvable
✗ Incorrect
DP is used when problems have overlapping subproblems and optimal substructure.
Explain in your own words when to choose recursion, dynamic programming, or greedy algorithms.
Think about problem structure and efficiency needs.
You got /3 concepts.
Describe the main difference between dynamic programming and greedy algorithms.
Focus on how each approach handles choices and subproblems.
You got /4 concepts.
Practice
(1/5)
1. Which approach is best suited when a problem has overlapping subproblems and optimal substructure?
easy
A. Simple Recursion
B. Dynamic Programming
C. Greedy Algorithm
D. Brute Force
Solution
Step 1: Understand problem characteristics
Overlapping subproblems mean the same smaller problems repeat. Optimal substructure means the best solution can be built from best solutions of smaller problems.
Step 2: Match approach to characteristics
Dynamic Programming stores results of subproblems to avoid recomputation, ideal for overlapping subproblems and optimal substructure.
Hint: Use DP when subproblems repeat and build optimal solutions [OK]
Common Mistakes:
Choosing greedy when subproblems overlap
Using simple recursion without memoization
Confusing optimal substructure with greedy choice
2. Which of the following C# code snippets correctly implements a greedy approach to find the maximum number of activities that don't overlap given start and end times arrays (assuming sorted by end time)?
easy
A. int count = 1; int lastEnd = end[0]; for (int i = 1; i < start.Length; i++) { if (start[i] >= lastEnd) { count++; lastEnd = end[i]; } } Console.WriteLine(count);
B. int count = 0; for (int i = 0; i < start.Length; i++) { if (start[i] > end[i]) count++; } Console.WriteLine(count);
C. int count = 1; for (int i = 1; i < start.Length; i++) { if (end[i] >= start[i-1]) count++; } Console.WriteLine(count);
D. int count = 0; foreach (var s in start) { count += s; } Console.WriteLine(count);
We select the first activity, then pick next activities starting after the last selected activity ends.
Step 2: Check code correctness
int count = 1; int lastEnd = end[0]; for (int i = 1; i < start.Length; i++) { if (start[i] >= lastEnd) { count++; lastEnd = end[i]; } } Console.WriteLine(count); initializes count to 1, tracks lastEnd, and increments count only if start[i] >= lastEnd, updating lastEnd. This matches greedy logic.
Final Answer:
the code that tracks lastEnd -> Option A
Quick Check:
Greedy activity selection code = int count = 1; int lastEnd = end[0]; for (int i = 1; i < start.Length; i++) { if (start[i] >= lastEnd) { count++; lastEnd = end[i]; } } Console.WriteLine(count); [OK]
Hint: Pick next activity starting after last selected ends [OK]
Common Mistakes:
Not sorting activities by end time before selection
Comparing start[i] with wrong end time
Counting activities incorrectly
3. What is the output of the following C# code that uses recursion to calculate Fibonacci numbers without memoization?
int Fib(int n) { if (n <= 1) return n; return Fib(n - 1) + Fib(n - 2); } Console.WriteLine(Fib(5));
4. The following C# code attempts to solve the coin change problem using recursion but has a bug. What is the bug?
int CoinChange(int[] coins, int amount) { if (amount == 0) return 0; if (amount < 0) return -1; int min = int.MaxValue; foreach (int coin in coins) { int res = CoinChange(coins, amount - coin); if (res >= 0 && res < min) min = 1 + res; } return min == int.MaxValue ? -1 : min; }
medium
A. No memoization causing repeated calculations
B. Incorrect base case for amount == 0
C. Returning -1 instead of 0 for amount < 0
D. Using foreach instead of for loop
Solution
Step 1: Analyze recursion and base cases
Base cases are correct: 0 returns 0, negative returns -1. The recursion tries all coins.
Step 2: Identify missing optimization
Without memoization, the function recalculates subproblems many times, causing inefficiency and possible stack overflow.
Final Answer:
No memoization causing repeated calculations -> Option A
Quick Check:
Missing memoization = No memoization causing repeated calculations [OK]
Hint: Add memo dictionary to avoid repeated calls [OK]
Common Mistakes:
Thinking base cases are wrong
Believing loop type causes bug
Ignoring performance issues
5. You want to find the minimum number of coins needed to make a given amount using coins of different denominations. Which approach is best and why?
hard
A. Greedy algorithm may fail for some coin sets
B. Simple iteration misses subproblem reuse
C. Recursion without memoization is inefficient
D. Dynamic programming ensures optimal solution efficiently
Solution
Step 1: Evaluate greedy approach limitations
Greedy works only if coin denominations are canonical (like US coins). Otherwise, it can fail to find minimum coins.
Step 2: Consider recursion and iteration drawbacks
Recursion without memoization repeats work; simple iteration without storing results misses subproblem reuse.
Step 3: Understand dynamic programming benefits
DP with bottom-up tabulation stores minimum coins for all amounts up to target, guaranteeing optimal and efficient solution.
Final Answer:
Dynamic programming ensures optimal solution efficiently -> Option D
Quick Check:
Minimum coins problem = DP bottom-up [OK]
Hint: Use DP tabulation for guaranteed minimum coins [OK]
Common Mistakes:
Assuming greedy always works
Ignoring performance of recursion
Not storing intermediate results
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.