AlgoViz
← Back to trail

Greedy: Activity Selection

Medium+90 XP

Pick the most non-overlapping activities by sorting on END time and always grabbing the next one that fits.

No visualization loaded.

Watch

i

Press Run to begin.

You have a bunch of activities, each with a start and end time, and you can only do one at a time. You want to do as MANY as possible without two overlapping. A greedy method solves it: sort the activities by when they finish, then sweep through and grab each one that starts after your last pick ended.

What does 'greedy' even mean?

Greedy means: at each step, grab the choice that looks best RIGHT NOW and never undo it. No planning ahead, no backtracking, no comparing every possibility — just commit to the locally-best move and keep going. It's the opposite of carefully trying all combinations. The surprising part is that for some problems this simple, stubborn strategy actually gives the perfect answer.

Why sort by END time? That feels random.

Because the activity that FINISHES earliest leaves the most room for everything after it. Think of your day as a hallway: picking the activity that gets out of the way soonest keeps the most open space for later activities to fit. So 'earliest finish' isn't random — it's the choice that protects the most future room, which is exactly what lets you fit the maximum number.

Why not just take the SHORTEST activity first? That seems greedier.

It can wreck the answer. Picture three activities: A = 1-5, B = 4-6, C = 5-9. The shortest is B (only 2 long), so 'shortest first' grabs B — but B overlaps BOTH A and C, so you end up with just 1 activity. Sorting by end time instead takes A (ends at 5) then C (starts at 5): 2 activities. 'Shortest first' looked clever and lost.

What about taking the EARLIEST start first?

Also broken. Imagine A = 0-10 and then B = 1-2, C = 3-4, D = 5-6. 'Earliest start' grabs A first — but A hogs the whole day and blocks B, C, and D, giving you 1 activity. 'Earliest end' skips the greedy-looking giant A and collects B, C, D instead: 3 activities. The earliest-FINISH rule is the only one of the three that's provably correct here.

When does greedy work, and when do I need something heavier like DP?

Greedy works when a problem has the 'safe first move' property: there's always a locally-best choice you can lock in without it ever blocking the best overall answer — like 'earliest end' here. When that's NOT true — when a choice that looks best now can force worse choices later (think 0/1 Knapsack, where grabbing the most valuable item can waste the bag) — greedy gives wrong answers and you need Dynamic Programming, which actually weighs the alternatives instead of committing blindly.

🧠Activity Selection: sort by END time, then sweep left to right taking every activity that starts after your last pick ended. Greedy commits to the locally-best move and never looks back — and here 'earliest finish' is provably the right move.
📈

How the work grows

input size n →work ↑
Time
O(n log n)
Space
O(n) — the sorted list

O(n log n) is good — the practical sorting speed. The work is dominated by sorting the activities by end time: O(n log n). The greedy sweep afterward is a single left-to-right pass that touches each activity once — O(n) — so the sort is the expensive part. No table, no recursion: greedy's payoff is that one pass replaces the exponential 'try every subset' search.

Faint dotted lines = O(1) (flat) and O(n) (straight) for comparison.

activity under decision nowchosen (no overlap)skipped (overlaps last pick)