Greedy approach makes the best choice at each step, hoping to find the overall best solution without reconsidering previous choices.
Click to reveal answer
beginner
What does Dynamic Programming (DP) do differently from Greedy?
DP solves problems by breaking them into smaller overlapping subproblems and storing their results to avoid repeated work, ensuring an optimal solution.
Click to reveal answer
intermediate
When should you prefer Greedy over DP?
Use Greedy when the problem has the greedy-choice property and optimal substructure, meaning local best choices lead to a global best solution.
Click to reveal answer
beginner
What is the 'optimal substructure' property?
A problem has optimal substructure if an optimal solution to the problem contains optimal solutions to its subproblems.
Click to reveal answer
intermediate
How can you check if a problem requires DP instead of Greedy?
If making a local best choice does not guarantee a global best solution or subproblems overlap, DP is needed to explore all possibilities and store results.
Click to reveal answer
Which property must a problem have for Greedy to work correctly?
AOverlapping subproblems
BGreedy-choice property
CMemoization
DBacktracking
✗ Incorrect
Greedy-choice property means local best choices lead to a global best solution, which is essential for Greedy.
What technique does Dynamic Programming use to avoid repeated work?
ASorting
BGreedy choice
CMemoization
DDivide and conquer without storage
✗ Incorrect
DP uses memoization to store results of subproblems and avoid recalculating them.
If a problem's subproblems do NOT overlap, which approach is usually better?
AGreedy
BDynamic Programming
CBacktracking
DBrute force
✗ Incorrect
When subproblems do not overlap and greedy-choice property holds, Greedy is simpler and efficient.
Which of these problems typically requires Dynamic Programming?
AFinding minimum coin change with unlimited coins
BFinding the largest number in a list
CSorting numbers
DFinding max in a sorted list
✗ Incorrect
Minimum coin change has overlapping subproblems and requires DP to find optimal solution.
What does it mean if a problem has 'overlapping subproblems'?
ASubproblems are independent
BNo subproblems exist
CSubproblems are solved once
DSubproblems repeat and share solutions
✗ Incorrect
Overlapping subproblems means the same smaller problems appear multiple times, ideal for DP.
Explain how to decide between using Greedy or Dynamic Programming for a problem.
Think about whether local best choices lead to global best and if subproblems repeat.
You got /5 concepts.
Describe the key differences between Greedy and Dynamic Programming approaches.
Focus on how each approach handles problem solving and solution storage.
You got /5 concepts.
Practice
(1/5)
1. Which of the following best describes when to use a greedy algorithm instead of dynamic programming?
easy
A. When the problem has overlapping subproblems and no optimal substructure
B. When the problem has an optimal substructure and no overlapping subproblems
C. When the problem requires checking all possible solutions
D. When the problem is unsolvable
Solution
Step 1: Understand greedy algorithm conditions
Greedy algorithms work when choosing the best option at each step leads to a global optimum, which means the problem has an optimal substructure and no overlapping subproblems.
Step 2: Compare with dynamic programming conditions
Dynamic programming is used when the problem has overlapping subproblems and optimal substructure, requiring storing intermediate results.
Final Answer:
When the problem has an optimal substructure and no overlapping subproblems -> Option B
Quick Check:
Greedy = optimal substructure + no overlap [OK]
Hint: Use greedy if no overlapping subproblems exist [OK]
Common Mistakes:
Confusing overlapping subproblems as a greedy condition
Using DP when greedy suffices
Assuming greedy always finds optimal solution
Ignoring problem structure before choosing approach
2. Which Rust code snippet correctly declares a vector and uses it to implement a greedy approach for selecting intervals sorted by end time?
easy
A. let intervals = vec![(1,3), (2,5), (4,7)]; intervals.reverse();
B. let intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort();
C. let mut intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort_by(|a,b| a.0.cmp(&b.0));
D. let mut intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort_by_key(|k| k.1);
Solution
Step 1: Identify correct vector declaration and sorting
let mut intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort_by_key(|k| k.1); declares a mutable vector and sorts it by the second element (end time), which is needed for greedy interval scheduling.
Step 2: Check other options for correctness
let intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort(); tries to sort an immutable vector and uses default sort (by first element), let mut intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort_by(|a,b| a.0.cmp(&b.0)); sorts by start time, not end time, and let intervals = vec![(1,3), (2,5), (4,7)]; intervals.reverse(); reverses without sorting.
Final Answer:
let mut intervals = vec![(1,3), (2,5), (4,7)]; intervals.sort_by_key(|k| k.1); -> Option D
Quick Check:
Sort intervals by end time with mutable vector [OK]
Hint: Sort intervals by end time for greedy scheduling [OK]
Common Mistakes:
Sorting by start time instead of end time
Using immutable vector when sorting is needed
Not sorting intervals before greedy selection
Using reverse instead of sort
3. What is the output of the following Rust code implementing a greedy approach to select maximum intervals?
let mut intervals = vec![(1,3), (2,5), (4,7)];
intervals.sort_by_key(|k| k.1);
let mut count = 0;
let mut end = 0;
for &(start, finish) in &intervals {
if start >= end {
count += 1;
end = finish;
}
}
println!("{}", count);
medium
A. 2
B. 3
C. 1
D. 0
Solution
Step 1: Sort intervals by end time
Sorted intervals: (1,3), (2,5), (4,7)
Step 2: Iterate and count non-overlapping intervals
First interval (1,3): start=1 >= end=0, count=1, end=3
Second interval (2,5): start=2 < end=3, skip
Third interval (4,7): start=4 >= end=3, count=2, end=7
Final Answer:
2 -> Option A
Quick Check:
Greedy interval count = 2 [OK]
Hint: Count intervals where start >= last end [OK]
Common Mistakes:
Counting overlapping intervals
Not updating end after selection
Sorting incorrectly
Confusing start and end values
4. The following Rust code attempts to solve the coin change problem using a greedy approach. What is the bug?
let coins = vec![1, 3, 4];
let mut amount = 6;
let mut count = 0;
for &coin in coins.iter().rev() {
while amount >= coin {
amount -= coin;
count += 1;
}
}
println!("{}", count);
medium
A. The amount variable is not mutable
B. The coins vector is not sorted ascending
C. Greedy fails because coin denominations do not guarantee optimal solution
D. The loop should not reverse the coins vector
Solution
Step 1: Understand greedy coin change limitation
Greedy works only if coin denominations are canonical (like 1,5,10). Here, 1,3,4 can cause greedy to fail.
Step 2: Check code behavior
Greedy picks 4 once (amount=2), then picks 1 twice (total 3 coins). But optimal is 2 coins (3+3).
Final Answer:
Greedy fails because coin denominations do not guarantee optimal solution -> Option C
Quick Check:
Greedy fails on non-canonical coins [OK]
Hint: Greedy fails if coin set is not canonical [OK]
Common Mistakes:
Assuming greedy always works for coin change
Ignoring coin order importance
Not checking for optimal substructure
Confusing mutability of variables
5. You want to find the minimum number of coins to make amount 6 using coins [1, 3, 4]. Which approach is best and why?
A) Greedy picking largest coin first
B) Brute force checking all combinations
C) Dynamic programming storing minimum coins for each amount
D) Sorting coins ascending and picking smallest first
hard
A. Dynamic programming storing minimum coins for each amount
B. Brute force checking all combinations
C. Greedy picking largest coin first
D. Sorting coins ascending and picking smallest first
Solution
Step 1: Analyze greedy approach limitations
Greedy may pick 4 then 1s, resulting in 3 coins, but optimal is 2 coins (3+3).
Step 2: Understand dynamic programming advantage
DP stores minimum coins needed for each amount, ensuring optimal solution even with tricky coin sets.
Step 3: Compare other options
Brute force is slow; sorting ascending and picking smallest first is not optimal strategy.
Final Answer:
Dynamic programming storing minimum coins for each amount -> Option A
Quick Check:
DP handles overlapping subproblems for optimal coin count [OK]
Hint: Use DP for minimum coins with tricky denominations [OK]
Common Mistakes:
Using greedy for non-canonical coin sets
Ignoring performance of brute force
Assuming sorting smallest first helps
Not recognizing overlapping subproblems
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.