Memra

Greedy strategy & activity selection

◈ 5 cards

The greedy-choice property and optimal substructure, proved by an exchange argument, applied to activity selection.

What makes an algorithm greedy

A greedy algorithm makes the choice that looks best right now and never reconsiders it. It commits to a locally optimal choice before solving any subproblem, then recurses on the one subproblem that remains. This is the opposite of dynamic programming, which solves subproblems first and only then chooses. Greedy is therefore top-down and DP is bottom-up; greedy considers exactly one choice per step where DP considers all of them.

Greedy does not always work. When it does, the problem has two properties:

  1. Greedy-choice property — a globally optimal solution can be built by making locally optimal (greedy) choices. The greedy choice may depend on choices made so far, but not on the solutions to future subproblems.
  2. Optimal substructure — an optimal solution to the problem contains optimal solutions to its subproblems. (DP needs this too; greedy uses it after assuming the greedy choice is already made.)

The activity-selection problem

You are given activities, each with a start time and a finish time (the activity occupies the half-open interval ). Two activities are compatible if their intervals do not overlap. The goal is to select a maximum-size set of mutually compatible activities — think of scheduling the most events possible in one lecture hall.

The greedy choice: sort the activities by finish time, then always take the next activity whose start time is at or after the finish time of the last one you took. Taking the earliest-finishing compatible activity leaves the resource free as soon as possible, maximizing room for the rest.

Worked example. With 11 activities sorted by finish time (CLRS Fig. 15.1):

Take (finishes at 4). The next compatible one is (starts at , finishes at 7). Then (starts at , finishes at 11). Then (starts at ). Result: — four activities, which is optimal.

Why earliest-finish is safe (Theorem 15.1)

The correctness rests on an exchange argument, the canonical proof for the greedy-choice property. Let be the earliest-finishing activity in a subproblem, and let be any maximum-size compatible set for that subproblem. Let be the earliest-finishing activity in . If , we are done. Otherwise build . Because , swapping out for keeps every later activity compatible, so is still valid and . Thus a maximum-size solution containing the greedy choice exists. ∎

After the sort, the selection loop is : each activity is examined once. Contrast this with the DP recurrence that the greedy choice collapses into a single choice per step.

012345678a1 [1,4)a1a1a1a2 [3,5)a2a2a3 [0,6)a3a3a3a3a3a3a4 [5,7)a4a4a5 [3,9)a5a5a5a5a5a5a6 [5,9)a6a6a6a6Column t is the hour [t, t+1). a1 finishes at 4, so a2 (starts 3) and a3 (starts 0) are rejected; a4starts at 5 >= 4 and is taken; a5 and a6 both start before 7.
The first six activities (already sorted by finish time) on one time line. Greedy takes a1, then the first activity that starts at or after 4.
sort keyfirst pickchosen setsizeearliest finisha1 [1,4)a1, a4, a8, a114earliest starta3 [0,6)a3, a7, a113a3 runs from 0 to 6 and alone blocks a1 and a2 — one early-starting hog costs two activities.
Why the greedy key must be finish time — same instance, two sort orders.
greedydynamic programmingchoice madebefore subproblemsafter subproblemssubproblems per step1all candidatesdirectiontop-downbottom-upactivity selectionΘ(n) after sortΘ(n²) recurrenceBecause the greedy choice cannot depend on subproblem solutions, exactly one subproblem survives eachstep.
Greedy commits before recursing; DP recurses before committing.
NORMAL ~/memra/learn/comp-372/greedy-strategy-activity-selection utf-8 LF