Greedy vs Dynamic Programming: How to Know Which to Apply
📖 Scenario: Imagine you are organizing a small event and need to decide how to allocate your budget to buy snacks. You want to maximize the number of snacks you can buy without exceeding your budget. Sometimes, a simple quick choice works best, but other times you need to think carefully about all options.
🎯 Goal: You will learn how to decide when to use a simple greedy approach and when to use dynamic programming by solving a snack buying problem step-by-step.
📋 What You'll Learn
Create a list of snack prices
Create a budget variable
Write a greedy function to pick snacks quickly
Write a dynamic programming function to pick snacks optimally
Print results of both methods to compare
💡 Why This Matters
🌍 Real World
Choosing items within a budget is common in shopping, resource allocation, and planning tasks.
💼 Career
Understanding when to use greedy or dynamic programming helps in solving optimization problems efficiently in software development and data science.
Progress0 / 4 steps
1
Create the snack prices list
Create a list called snackPrices with these exact values: [2, 3, 1, 4, 6]
DSA Typescript
Hint
Use const snackPrices: number[] = [2, 3, 1, 4, 6]; to create the list.
2
Set the budget variable
Create a variable called budget and set it to 10
DSA Typescript
Hint
Use const budget: number = 10; to set the budget.
3
Write a greedy function to pick snacks quickly
Write a function called greedySnackSelection that takes snackPrices and budget as parameters and returns the maximum number of snacks you can buy by always picking the cheapest snack first without exceeding the budget. Use sorting and a for loop.
DSA Typescript
Hint
Sort the snack prices from cheapest to expensive. Then pick snacks one by one until the budget is reached.
4
Write a dynamic programming function and print results
Write a function called dpSnackSelection that takes snackPrices and budget and returns the maximum number of snacks you can buy without exceeding the budget using dynamic programming. Then print the results of greedySnackSelection(snackPrices, budget) and dpSnackSelection(snackPrices, budget).
DSA Typescript
Hint
Use a 2D array to store the best number of snacks for each budget and snack count. Then print both results to compare.
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 the greedy choice property and optimal substructure
B. When the problem requires checking all possible combinations
C. When the problem has overlapping subproblems but no optimal substructure
D. When the problem needs to store all intermediate results
Solution
Step 1: Understand greedy choice property
A greedy algorithm works when choosing the best option at each step leads to a global optimum.
Step 2: Check optimal substructure
Optimal substructure means the optimal solution can be built from optimal solutions of subproblems.
Final Answer:
When the problem has the greedy choice property and optimal substructure -> Option A
Hint: Use greedy if local best leads to global best [OK]
Common Mistakes:
Confusing overlapping subproblems with greedy applicability
Using greedy when problem needs full exploration
Ignoring optimal substructure requirement
2. Which syntax correctly declares a memoization object in TypeScript for dynamic programming?
easy
A. var memo: number[] = [];
B. let memo = new Map();
C. const memo: Record = {};
D. const memo = {} as number[];
Solution
Step 1: Understand memo type for DP
Memoization stores results with keys, so Record is suitable.
Step 2: Check syntax correctness
const memo: Record = {}; correctly declares an empty object with number keys and values.
Final Answer:
const memo: Record = {}; -> Option C
Quick Check:
Memo object uses Record type [OK]
Hint: Use Record for memo objects [OK]
Common Mistakes:
Using var instead of const or let
Incorrect type assertion for memo
Using Map without type parameters
3. Consider this TypeScript code snippet for a problem that can be solved by greedy or DP:
function maxSum(arr: number[]): number {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] > 0) sum += arr[i];
}
return sum;
}
console.log(maxSum([-1, 2, 3, -5, 4]));
What is the output?
medium
A. 9
B. 4
C. 0
D. Error
Solution
Step 1: Trace the loop and sum positive numbers
Positive numbers are 2, 3, and 4. Sum = 2 + 3 + 4 = 9.
Step 2: Confirm return value
The function returns sum = 9, so console.log prints 9.
Final Answer:
9 -> Option A
Quick Check:
Sum positives = 9 [OK]
Hint: Sum only positive numbers for max sum greedy [OK]
Common Mistakes:
Adding negative numbers mistakenly
Returning zero instead of sum
Confusing output with array length
4. The following TypeScript function is intended to solve the Fibonacci sequence using DP with memoization. What is the bug?
function fib(n: number, memo: Record = {}): number {
if (n <= 1) return n;
if (memo[n]) return memo[n];
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n];
}
console.log(fib(5));
medium
A. The recursive calls should be fib(n + 1) and fib(n + 2)
B. The base case should be 'if (n < 0) return 0;'
C. The function should not use default parameter for memo
D. The memo check should be 'if (memo[n] !== undefined)' to handle zero
Solution
Step 1: Analyze memo check condition
Checking 'if (memo[n])' fails when memo[n] is 0, which is falsy.
Step 2: Correct memo check
Use 'if (memo[n] !== undefined)' to correctly detect stored values including zero.
Final Answer:
The memo check should be 'if (memo[n] !== undefined)' to handle zero -> Option D
Quick Check:
Memo check must handle zero values [OK]
Hint: Check memo with !== undefined, not truthy check [OK]
Common Mistakes:
Using truthy check for memo causing wrong cache hits
Wrong base case for Fibonacci
Incorrect recursive call directions
5. You have a set of tasks with durations and deadlines. You want to maximize the number of tasks completed before their deadlines. Which approach is best and why?
interface Task {
duration: number;
deadline: number;
}
function scheduleTasks(tasks: Task[]): number {
// Implementation needed
}
hard
A. Use dynamic programming to try all subsets and pick max count
B. Use a greedy algorithm sorting tasks by earliest deadline to maximize count
C. Use greedy sorting by longest duration first to minimize total time
D. Use dynamic programming to minimize total duration ignoring deadlines
Solution
Step 1: Understand problem goal
Maximize number of tasks completed before deadlines means scheduling tasks efficiently.
Step 2: Identify best approach
Greedy algorithm sorting by earliest deadline ensures maximum tasks fit before deadlines.
Final Answer:
Use a greedy algorithm sorting tasks by earliest deadline to maximize count -> Option B
Quick Check:
Earliest deadline first greedy maximizes tasks [OK]
Hint: Sort tasks by earliest deadline for max count [OK]
Common Mistakes:
Trying all subsets with DP causing inefficiency
Sorting by longest duration wastes time
Ignoring deadlines in scheduling
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.