1. Home
  2. Design & Analysis of Algorithms
  3. Activity Selection (Greedy)

Activity Selection (Greedy)

Attend as many non-overlapping events as possible. Sort by finish time and always take the earliest finisher that fits.

Interactive 3DBeginner10 min readDAAUpdated

Drag to rotate · Right-drag to pan · Click, then scroll to zoom · Space play · ←→ step

What's happening

Pseudocode

    Try this in the 3D model

    • Run the Classic example. Which activities are chosen, and which ones are skipped because of overlap?
    • Notice a3 = [0, 6] starts earliest. Why does choosing it first give a worse answer?
    • Press Random activities a few times. Is the chosen set always the same size as the best possible?
    • Look at the pink marker. What does "last" represent?

    The problem

    You are given n activities, each with a start and a finish time. You can attend only one at a time. Choose the largest set of activities that do not overlap.

    Greedy rule

    1. Sort the activities by finish time.
    2. Take the first one.
    3. Walk through the rest. Take an activity if its start is at or after the finish of the last one you took. Otherwise skip it.
    sort by finish time
    last ← −∞;  chosen ← [ ]
    for each activity (s, f):
        if s ≥ last:  choose it;  last ← f

    Worked example

    Sorted by finish: a1 [1,4], a2 [3,5], a3 [0,6], a4 [5,7], a5 [3,9], a6 [5,9], a7 [6,10], a8 [8,11], a9 [8,12], a10 [2,14], a11 [12,16].

    Activity Start vs last finish Decision
    a1 [1,4] 1 ≥ −∞ choose, last = 4
    a2, a3 start 3 and 0 are before 4 skip
    a4 [5,7] 5 ≥ 4 choose, last = 7
    a5, a6, a7 start 3, 5, 6 are before 7 skip
    a8 [8,11] 8 ≥ 7 choose, last = 11
    a9, a10 start 8 and 2 are before 11 skip
    a11 [12,16] 12 ≥ 11 choose

    Chosen: a1, a4, a8, a11, 4 activities, the maximum possible.

    Why the greedy choice is safe

    Suppose an optimal solution starts with some other activity. Replace its first activity by the one with the earliest finish. That one ends no later, so everything that followed still fits, and the solution is no worse. Repeating the argument shows greedy is optimal.

    Wrong greedy rules

    • Earliest start can pick one very long activity that blocks everything (a3 [0,6] or a10 [2,14] above).
    • Shortest duration can pick a short event in the middle that overlaps two longer ones that could have both been chosen.

    Only the earliest finish rule always works. This is a typical exam question on greedy correctness, together with Huffman coding and Prim/Kruskal.

    Code

    def select_activities(acts):
        acts = sorted(acts, key=lambda a: a[1])
        chosen, last = [], float('-inf')
        for s, f in acts:
            if s >= last:
                chosen.append((s, f))
                last = f
        return chosen
    
    print(select_activities([(1,4),(3,5),(0,6),(5,7),(3,9),(5,9),(6,10),(8,11),(8,12),(2,14),(12,16)]))
    # [(1, 4), (5, 7), (8, 11), (12, 16)]

    Common mistakes

    • Sorting by start time or duration instead of finish time.
    • Using s > last when the problem allows back-to-back events (s ≥ last).
    • Forgetting to update last after choosing an activity.

    Complexity at a glance

    Case / operationTimeWhy
    Sorting by finish timeO(n log n)Skipped if the input is already sorted.
    Greedy scanO(n)One pass, comparing start time with the last finish.
    Extra spaceO(1) extra (plus the output)

    Quick check

    Test yourself — pick an answer to see if you got it.

    1. By which key should the activities be sorted for the greedy algorithm to be optimal?

    2. When is an activity compatible with the last chosen one?

    3. What is the running time if the activities are not sorted yet?

    4. Why does "always pick the shortest activity" fail?

    Saved only in this browser — no account needed.
    Spotted a mistake or a bug in the 3D model?

    Report a mistake

    in Activity Selection (Greedy). Thank you — every report makes the lesson better for the next reader.

    We'll also include a link to the step of the 3D model you're on and your browser type, so we can reproduce it.