DSA Notes
Master greedy algorithms from the ground up — what makes an algorithm greedy, the greedy choice property, optimal substructure, exchange argument proof technique, when greedy works vs when it fails, comparison with DP, and examples of correct and incorrect greedy choices.
What Is a Greedy Algorithm?
A greedy algorithm solves problems by making the locally optimal choice at each step, with the hope that these local choices lead to a globally optimal solution.
At each decision point, a greedy algorithm:
- Looks at the current state
- Makes the best possible choice for the immediate step (without looking ahead)
- Never reconsiders this choice — the decision is irrevocable
The word "greedy" reflects the strategy: take the best thing available right now, don't think about the future.
The Two Essential Properties
A problem can be solved greedily if and only if it has these two properties:
Property 1 — Greedy Choice Property
A globally optimal solution can be built by making locally optimal choices. When we make the greedy choice, there exists an optimal solution consistent with it.
This means: you never need to undo a greedy choice. The choice you make now will never be "wrong" — there is always an optimal solution that includes it.
Property 2 — Optimal Substructure
After making a greedy choice, the remaining subproblem has the same structure as the original. The optimal solution to the whole problem contains the optimal solution to the remaining subproblem.
(This is the same property required for dynamic programming, but greedy additionally requires the greedy choice property.)
How to Prove a Greedy Algorithm is Correct
Method 1 — Exchange Argument
This is the most common proof technique for greedy algorithms.
Structure: "Suppose an optimal solution does NOT make the greedy choice. Show that swapping the greedy choice in (while swapping out whatever the optimal solution chose) makes the solution no worse."
| Example | Activity Selection Problem |
| Greedy | Always pick the activity that ends earliest. |
| Claim | This greedy choice is in some optimal solution. |
| Case 1 | a = b. The greedy choice is already in OPT. Done. |
| Case 2 | a ≠ b. Since a has the earliest end time, end(a) ≤ end(b). |
Method 2 — Contradiction
Assume the greedy algorithm does NOT produce an optimal solution. Show this leads to a contradiction.
Method 3 — Induction
Base case: greedy is correct for small inputs. Inductive step: if greedy is correct for n-1 elements, it's correct for n elements.
When Greedy Fails — Counter-Examples
Not every problem has the greedy choice property. Learning when greedy FAILS is as important as knowing when it works.
Failure 1 — Coin Change (Non-Standard Denominations)
| Denominations | [1, 3, 4], Target: 6 |
| Greedy | 4 + 1 + 1 = 3 coins ← WRONG! |
| Optimal | 3 + 3 = 2 coins |
| Why it fails | Choosing 4 (locally best) prevents using 3+3 (globally best). |
Failure 2 — 0/1 Knapsack
| Items | [(weight=3, value=4), (weight=4, value=5), (weight=5, value=6)] |
| Capacity | 7 |
| Take Item 1 (w=3) | remaining capacity=4 |
| Take Item 2 (w=4) | remaining capacity=0 |
| Take Item 2 + Item 3 | weight=4+5=9 > 7, doesn't fit |
| Take Item 1 + Item 3 | weight=3+5=8 > 7, doesn't fit |
| Items | weight=[3,4,5], value=[4,5,6], capacity=7 |
| Take items 1+2 | w=3+4=7, value=4+5=9 ← greedy got this! |
| Take items 1+3 | w=3+5=8 > 7, invalid |
| Take items 2+3 | w=4+5=9 > 7, invalid |
| Counter-example | items [(w=10,v=60),(w=20,v=100),(w=30,v=120)], cap=50 |
| Greedy by v/w: v/w = [6, 5, 4], take item 1 then item 2 | v=60+100=160 but w=30>50... |
| Actually w=10+20=30 ≤ 50, also take item 3 | 10+20+30=60>50, take item 3 not item 2: |
| item 1+3 | w=40, v=180, item 2+3: w=50, v=220 ← optimal! |
| Optimal | items 2+3 = value 220 |
| Why it fails | Unlike fractional knapsack, you can't take fractions. |
Greedy vs Dynamic Programming
| Aspect | Greedy | Dynamic Programming |
|---|---|---|
| Decision making | One locally optimal choice | Consider all choices |
| Revisiting decisions | Never | Not needed (memoization handles it) |
| Correctness | Requires greedy choice property | Always correct if substructure holds |
| Speed | Usually O(n log n) | Usually O(n²) or O(n×W) |
| Code complexity | Usually simple | More complex |
| Problems | Activity selection, Huffman, Dijkstra | Knapsack, LCS, edit distance |
Key question: "Does making the locally optimal choice now prevent us from finding a better solution later?"
- If NO → Greedy works
- If YES → Need DP
Classic Greedy Problems
| Problem | Greedy Strategy | Time |
|---|---|---|
| Activity Selection | Pick earliest-ending activity | O(n log n) |
| Fractional Knapsack | Pick by value/weight ratio | O(n log n) |
| Job Sequencing | Sort by deadline | O(n log n) |
| Huffman Coding | Merge two lowest-frequency nodes | O(n log n) |
| Dijkstra's | Process closest unvisited vertex | O((V+E) log V) |
| Kruskal's MST | Add cheapest safe edge | O(E log E) |
| Prim's MST | Add cheapest connecting edge | O(E log V) |
| Interval Scheduling | Minimize late jobs | O(n log n) |
The Greedy Algorithm Template
def greedy_algorithm(items, constraint):
"""
General greedy template:
1. Sort items by greedy criterion
2. Iterate and make greedy choice at each step
3. Accumulate result
"""
# Step 1: Sort by greedy criterion (most important step!)
sorted_items = sorted(items, key=greedy_criterion)
result = initial_state
for item in sorted_items:
if is_feasible(result, item):
result = apply(result, item) # Irrevocable choice
return resultThe sorting step is the key design decision — what criterion to sort by determines whether the greedy approach is correct.
Summary
Greedy algorithms make locally optimal choices at each step:
- When correct: Greedy choice property + optimal substructure
- Proof technique: Exchange argument — swap greedy choice into any optimal solution without making it worse
- Failure conditions: When local optima lead to global suboptimality (use DP instead)
- Efficiency advantage: Usually O(n log n) — much faster than DP when applicable
The art of greedy algorithms is recognizing when the greedy choice property holds — and proving it rigorously when it does.
*Next Lesson: Activity Selection Problem*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Greedy Algorithms — Complete Introduction with Proof Techniques.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, greedy, introduction, greedy algorithms — complete introduction with proof techniques
Related Data Structures & Algorithms Topics