Greedy Algorithms
Greedy algorithms make locally optimal choices at each step. GATE tests when greedy works, classic problems, and knowing when greedy fails.
Key Points
- ·Greedy works when: greedy choice property + optimal substructure hold
- ·Activity selection: sort by finish time — O(n log n)
- ·Huffman coding: always merge two lowest-frequency nodes
- ·Fractional knapsack: sort by value/weight ratio — greedy works
- ·0/1 knapsack: greedy FAILS — needs DP
- ·Proof technique: exchange argument
What is Greedy?
Greedy algorithms make the locally best choice at each step without looking back. Think of a person who, at every intersection, always takes the road that seems shortest right now — without planning the full route.
Sometimes this works perfectly (Dijkstra, Prim, Huffman). Sometimes it fails catastrophically (0/1 knapsack with bad denominations).
Two properties needed for greedy to work correctly: 1. Greedy Choice Property: A globally optimal solution can be reached by making locally optimal choices. 2. Optimal Substructure: Optimal solution to the problem contains optimal solutions to subproblems.
Activity Selection — When to Schedule Meetings
Problem: You have a meeting room. Given n activities with start and finish times, select the maximum number of non-overlapping activities.
Greedy strategy: Always pick the activity that finishes earliest (leaves maximum time for future activities).
Activities: [(1,4), (3,5), (0,6), (5,7), (3,9), (5,9), (6,10), (8,11), (8,12), (2,14)]
Sort by finish time: [(1,4), (3,5), (0,6), (5,7), (3,9), (5,9), (6,10), (8,11), (8,12), (2,14)]
Select (1,4): finish=4. ✓
Skip (3,5): starts at 3, overlaps with (1,4) since 3 < 4.
Skip (0,6): starts at 0, overlaps.
Select (5,7): starts at 5 ≥ 4. ✓
Skip (3,9), (5,9): overlap.
Select (6,10)? Wait — starts at 6 < 7. Skip.
Actually: select (8,11): starts at 8 ≥ 7. ✓
Done: 3 activities selected.
Why finish-earliest works: Choosing the earliest-finishing activity leaves the maximum remaining time for other activities. Proof by exchange argument: if optimal solution uses activity B instead of earlier-finishing A, swapping A for B doesn't reduce the count (A finishes no later than B).
Huffman Coding — Optimal Data Compression
Problem: Assign binary codes to characters so frequently used characters get shorter codes, minimising total encoded length.
Greedy strategy: Always merge the two nodes with the lowest frequency.
Characters and frequencies:
a:5, b:9, c:12, d:13, e:16, f:45
Step 1: Merge a(5) and b(9) → new node (14)
Step 2: Merge (14) and c(12) → new node (26)
Step 3: Merge d(13) and e(16) → new node (29)
Step 4: Merge (26) and (29) → new node (55)
Step 5: Merge f(45) and (55) → root (100)
Huffman tree:
(100)
/ \
f(45) (55)
/ \
(26) (29)
/ \ / \
(14) c d e
/ \
a b
Codes: f=0, c=101, d=110, e=111, a=1000, b=1001
Frequently used f gets shortest code (1 bit), rarely used a and b get longer codes (4 bits). Total encoded length is minimised.
Time: O(n log n) with a min-heap.
Fractional Knapsack — Greedy Works Here
Problem: Items with weights and values. Can take fractions of items. Maximise value in capacity W.
Greedy: Sort by value/weight ratio (descending). Take items greedily; if last item doesn't fit, take the fraction that fits.
Items: (w=10, v=60), (w=20, v=100), (w=30, v=120)
Capacity: W=50
Ratios: 60/10=6, 100/20=5, 120/30=4
Take full item 1 (w=10, v=60). Remaining W=40.
Take full item 2 (w=20, v=100). Remaining W=20.
Take 2/3 of item 3 (w=20, v=80). Remaining W=0.
Total value = 60 + 100 + 80 = 240
Why greedy works: Taking more of higher value-density always improves or maintains the objective. Formal proof by exchange argument.
When Greedy FAILS — 0/1 Knapsack
You CANNOT take fractions. A greedy approach (take highest value-density first) fails.
Items: (w=10, v=60), (w=20, v=100), (w=30, v=120)
Capacity: W=50
Greedy by ratio: Take item 1 (v=60, w=10). Take item 2 (v=100, w=20). Now W=20 left.
Item 3 needs w=30 — doesn't fit. Nothing else fits.
Greedy total: 60 + 100 = 160
But OPTIMAL is: Take items 2 and 3 (w=20+30=50, v=100+120=220).
Optimal total: 220 > 160
Greedy failed! 0/1 Knapsack requires Dynamic Programming.
Greedy vs DP — Decision Table
| Problem | Greedy? | Why |
|---|---|---|
| Activity selection | ✓ | Exchange argument works |
| Huffman coding | ✓ | Locally best merge is globally optimal |
| Fractional knapsack | ✓ | Can take fractions → greedy choice is always valid |
| 0/1 knapsack | ✗ | Cannot take fractions — need to try all combinations |
| Coin change (standard: 1,5,10,25) | ✓ | Canonical coin systems are greedy-safe |
| Coin change (arbitrary: 1,3,4) | ✗ | Example: sum=6 → greedy gives {4,1,1}, DP gives {3,3} |
Quick Check
Q1. Activities: (0,3), (1,4), (2,5), (3,6). Select maximum non-overlapping.
Sort by finish: (0,3), (1,4), (2,5), (3,6)
Select (0,3). Skip (1,4) — overlap. Skip (2,5) — overlap.
Select (3,6) — starts at 3 ≥ 3. ✓
Answer: **2 activities**.
Q2. Is Dijkstra's algorithm a greedy algorithm?
Answer: Yes — at each step, Dijkstra greedily picks the vertex with the smallest current distance. It works because edge weights are non-negative (greedy choice property holds).
Key Formulas
- Huffman entropy: Average code length ≥ H(X) = −Σ p(x) log₂ p(x)
- Activity selection: Sort by finish time; select if start ≥ last selected finish
GATE Exam Tips
- ★Greedy does NOT work for 0/1 knapsack — this exact distinction appears in GATE
- ★Huffman gives optimal prefix-free code — no codeword is a prefix of another
- ★Activity selection: sort by FINISH time, not start time
- ★Coin change with {1,3,4}, sum=6: greedy gives 3 coins, DP gives 2 coins — know this counterexample
Finished reading this topic?
Mark it complete to track your study progress.