🍕 Greedy Algorithms: The “Biggest Slice First” Strategy
The Universal Analogy: The Pizza Party Problem
Imagine you’re at a pizza party with your friends. The pizza is cut into slices of different sizes. You’re really hungry, and you want to eat as much as possible. What do you do?
You grab the BIGGEST slice first!
Then the next biggest. Then the next.
That’s it. That’s a greedy algorithm. You make the best choice RIGHT NOW without worrying about what comes later.
🧠 Greedy Algorithm Fundamentals
What Makes an Algorithm “Greedy”?
A greedy algorithm is like a hungry person at a buffet:
- Look at your options
- Pick the best one RIGHT NOW
- Never look back or change your mind
- Repeat until you’re done
The Golden Rule
“Always make the locally optimal choice and hope it leads to a globally optimal solution.”
When Does Greedy Work?
Think of it like building with LEGO blocks:
✅ Works when: Each good choice leads to more good choices ❌ Fails when: The best choice now blocks better choices later
# The Greedy Pattern
def greedy_solve(problem):
solution = []
while problem_not_solved:
# Find the best choice RIGHT NOW
best = find_best_option()
# Take it!
solution.append(best)
# Remove it from options
update_problem()
return solution
Simple Example: Making Change
You need to give ₹93 in change using the fewest coins. Coins available: ₹50, ₹20, ₹10, ₹5, ₹2, ₹1
Greedy approach:
- Use the BIGGEST coin that fits: ₹50 → Left: ₹43
- Next biggest that fits: ₹20 → Left: ₹23
- Next: ₹20 → Left: ₹3
- Next: ₹2 → Left: ₹1
- Finally: ₹1 → Done!
Answer: ₹50 + ₹20 + ₹20 + ₹2 + ₹1 = 5 coins
🗓️ Activity Selection Problem
The Story
You’re a busy kid with a PACKED Saturday! You want to do as many fun activities as possible.
| Activity | Start | End |
|---|---|---|
| Swimming | 9 AM | 11 AM |
| Movies | 10 AM | 1 PM |
| Gaming | 11 AM | 12 PM |
| Pizza Party | 12 PM | 2 PM |
| Soccer | 2 PM | 4 PM |
Problem: Some activities overlap! You can’t swim AND watch movies at the same time.
The Greedy Trick
Always pick the activity that ENDS EARLIEST!
Why? Because it frees up your time for more activities later.
def activity_selection(activities):
# Sort by end time (earliest first)
activities.sort(key=lambda x: x[1])
selected = [activities[0]]
last_end = activities[0][1]
for start, end in activities[1:]:
# If this activity starts after
# the last one ends, take it!
if start >= last_end:
selected.append((start, end))
last_end = end
return selected
Walking Through Our Example
- Sort by end time: Gaming(12), Swimming(11), Movies(1PM), Pizza(2PM), Soccer(4PM)
- Pick Gaming (ends at 12)
- Skip Swimming (overlaps)
- Skip Movies (overlaps)
- Pick Pizza Party (starts at 12, ends at 2)
- Pick Soccer (starts at 2, ends at 4)
Result: Gaming → Pizza Party → Soccer (3 activities!)
🏢 Meeting Rooms Problem
The Story
You’re the boss of a company. Everyone wants to use the conference room today! How many rooms do you need so everyone can have their meeting?
| Meeting | Time |
|---|---|
| Team A | 9-10 |
| Team B | 9-11 |
| Team C | 10-11 |
| Team D | 11-12 |
The Greedy Insight
Think of it like a restaurant:
- When someone arrives → they need a table
- When someone leaves → that table is free again
Track the MAXIMUM number of overlapping meetings!
def min_meeting_rooms(meetings):
events = []
for start, end in meetings:
events.append((start, 'arrive'))
events.append((end, 'leave'))
# Sort: if same time, 'leave' before 'arrive'
events.sort(key=lambda x: (x[0], x[1] == 'arrive'))
rooms_needed = 0
current_rooms = 0
for time, action in events:
if action == 'arrive':
current_rooms += 1
rooms_needed = max(rooms_needed, current_rooms)
else:
current_rooms -= 1
return rooms_needed
Our Example
- 9:00 → Team A arrives (1 room)
- 9:00 → Team B arrives (2 rooms) ← Peak!
- 10:00 → Team A leaves (1 room)
- 10:00 → Team C arrives (2 rooms)
- 11:00 → Team B leaves (1 room)
- 11:00 → Team C leaves (0 rooms)
- 11:00 → Team D arrives (1 room)
- 12:00 → Team D leaves (0 rooms)
Answer: You need 2 rooms!
📅 Interval Scheduling
The Story
This is like Activity Selection’s big sibling. You have jobs with start and end times, but each job has a different value (money you earn).
| Job | Time | Pay |
|---|---|---|
| Babysitting | 1-4 | ₹100 |
| Tutoring | 3-5 | ₹50 |
| Dog Walking | 4-6 | ₹80 |
Two Flavors
Flavor 1: Maximum Jobs (Classic Greedy) → Pick earliest ending times → Same as Activity Selection!
Flavor 2: Maximum Value (Weighted) → This needs Dynamic Programming (greedy alone won’t work!) → But we can still use greedy thinking as a starting point
# Maximum non-overlapping intervals
def max_intervals(intervals):
intervals.sort(key=lambda x: x[1])
count = 0
last_end = float('-inf')
for start, end in intervals:
if start >= last_end:
count += 1
last_end = end
return count
🦘 Jump Game
The Story
You’re a frog on lily pads! Each lily pad has a number that tells you the maximum distance you can jump from there.
Can you reach the last lily pad?
Lily pads: [2, 3, 1, 1, 4]
↑
Start
- From pad 0 (value 2): Jump up to 2 pads
- From pad 1 (value 3): Jump up to 3 pads
- And so on…
The Greedy Magic
Track how FAR you can possibly reach!
At each step, update your “farthest reachable” position.
def can_jump(nums):
farthest = 0
for i in range(len(nums)):
# Can we even reach this pad?
if i > farthest:
return False
# Update farthest we can reach
farthest = max(farthest, i + nums[i])
# Did we reach the end?
if farthest >= len(nums) - 1:
return True
return True
Walking Through [2, 3, 1, 1, 4]
| Position | Value | Farthest |
|---|---|---|
| 0 | 2 | max(0, 0+2) = 2 |
| 1 | 3 | max(2, 1+3) = 4 |
| 2 | 1 | max(4, 2+1) = 4 |
At position 1, farthest = 4, which reaches the end!
Answer: Yes, we can reach the last lily pad!
Jump Game II: Minimum Jumps
What’s the fewest jumps to reach the end?
def min_jumps(nums):
jumps = 0
current_end = 0
farthest = 0
for i in range(len(nums) - 1):
farthest = max(farthest, i + nums[i])
# Time to make a jump!
if i == current_end:
jumps += 1
current_end = farthest
return jumps
⛽ Gas Station Problem
The Story
You’re driving a car in a circle. There are gas stations along the way. Each station:
- Gives you some gas
- The road to the NEXT station costs some gas
Can you complete the circle? If yes, where should you start?
Stations: A B C D
Gas: 4 6 1 2
Cost: 3 4 5 1
The Greedy Secret
If the total gas ≥ total cost, a solution EXISTS!
And the trick: Start right AFTER the point where you ran out of gas!
def can_complete_circuit(gas, cost):
# First check: Is it even possible?
if sum(gas) < sum(cost):
return -1
start = 0
tank = 0
for i in range(len(gas)):
tank += gas[i] - cost[i]
# Ran out of gas!
if tank < 0:
# Start from the NEXT station
start = i + 1
tank = 0
return start
Why Does This Work?
Imagine you’re walking and you fall into a hole at station C.
Everything BEFORE station C wasn’t strong enough to carry you through.
So start AFTER the hole (at station D)!
If total gas ≥ total cost, starting from D will definitely work.
📋 Task Scheduler
The Story
You’re a chef with orders to make. Each order takes the same time, but you can’t make the same dish twice in a row (the pan needs to cool down!).
Orders: A, A, A, B, B, C Cooldown: 2 (wait 2 other tasks before repeating)
The Greedy Strategy
Always cook the dish you have the MOST of!
Why? The dish with most copies is the “bottleneck.” Handle it first!
from collections import Counter
def least_interval(tasks, n):
counts = Counter(tasks)
max_count = max(counts.values())
# How many tasks have the max count?
max_count_tasks = sum(
1 for c in counts.values()
if c == max_count
)
# Formula: frame-based calculation
intervals = (max_count - 1) * (n + 1) + max_count_tasks
# At minimum, we need len(tasks) intervals
return max(intervals, len(tasks))
Visual Example
Tasks: A, A, A, B, B, C Cooldown n = 2
Building the schedule:
A _ _ A _ _ A
↓ ↓ ↓ ↓
A B C A B _ A
We have 3 A’s, so we create 3 “frames” of size (n+1) = 3:
- Frame 1: A, B, C
- Frame 2: A, B, idle
- Frame 3: A
Total time: 8 units
The Magic Formula Explained
intervals = (max_count - 1) × (n + 1) + max_count_tasks
= (3 - 1) × (2 + 1) + 1
= 2 × 3 + 1
= 7
But we have 6 tasks, so answer = max(7, 6) = 7
Wait, I said 8 earlier! Let me recount: A B C A B _ A = 7 slots. Yes, 7 is correct!
🎯 Summary: When to Use Greedy
| Problem Type | Greedy Signal | Strategy |
|---|---|---|
| Activity Selection | Max activities | Pick earliest END |
| Meeting Rooms | Min rooms | Count overlaps |
| Interval Scheduling | Max non-overlap | Sort by end |
| Jump Game | Can reach? | Track farthest |
| Gas Station | Complete circle? | Start after failure |
| Task Scheduler | Min time | Handle max-frequency first |
The Greedy Checklist
✅ Does choosing the best NOW help the overall goal? ✅ Do I never need to “undo” a choice? ✅ Does sorting help identify the “best” choice?
If yes to all three → Greedy might work!
🚀 You’ve Got This!
Greedy algorithms are like life advice from a wise pizza lover:
“Don’t overthink it. Grab the best slice now. Keep grabbing. Be happy.”
Not every problem can be solved greedily, but when it works, it’s elegant, fast, and beautiful.
Now go forth and be greedy (algorithmically)! 🍕
