The Greedy Method
A greedy algorithm builds a solution one locally-best choice at a time and never looks back. We isolate the two properties that make this work — the greedy-choice property and optimal substructure — prove the canonical activity-selection algorithm correct with an exchange argument, watch greedy fail on the 0/1 knapsack, and glimpse matroids as the theory that says exactly when the greedy method is optimal.
╌╌╌╌
A greedy algorithm builds up a solution piece by piece, and at every step it takes the option that looks best right now (the largest, the smallest, the cheapest, the soonest), ignoring the choices still to come and never revisiting a choice already made. The bet is that locally optimal choices add up to a globally optimal solution.
Sometimes the bet pays off, and the result is a simple and fast algorithm. Often it does not, and the algorithm returns wrong answers. The central task of the greedy method is telling the two cases apart, and the only reliable way is a proof. Erickson puts the warning bluntly: most greedy algorithms are wrong, and a greedy strategy that has not been proved correct should be treated as a plausible guess, nothing more.1
What makes greedy work
Dynamic programming, which we meet in a later module, considers all the ways a problem decomposes and picks the best. Greedy algorithms commit to one choice immediately and recurse on what remains. Two structural properties make that commitment valid.
- The greedy-choice property.2 There exists an optimal solution that contains the greedy (locally optimal) first choice. We never have to look ahead: a best-looking-now choice is safe, since some optimal solution agrees with it.
- Optimal substructure. After making the greedy choice, what remains is a smaller instance of the same problem, and an optimal solution to the whole is the greedy choice plus an optimal solution to that subproblem.
Optimal substructure is shared with dynamic programming. The greedy-choice property is the extra ingredient: it collapses the many subproblems DP would explore down to a single one. That is why greedy algorithms, when they work, are so much faster than their DP cousins. Proving these two properties, not running the code on a few examples, is what separates a correct greedy algorithm from a hopeful heuristic.
The canonical example: activity selection
We are given activities that compete for one resource: a lecture hall, a tennis court, a single CPU. Activity has a start time and a finish time , and occupies the half-open interval . Two activities are compatible if their intervals do not overlap. We want to select a largest possible set of mutually compatible activities.
Drawn on a number line, an instance and one optimal schedule look like this. The shaded bars are the chosen activities; they tile the timeline without overlap.
The chosen set uses four activities; no compatible set is larger. The question is which greedy rule finds such a set.
Choosing the right greedy rule
Several plausible rules suggest themselves, and most are wrong:
- Earliest start first? A single activity that starts at time but runs forever blocks everything — wrong.
- Shortest duration first? A short activity wedged between two longer ones can knock out two compatible activities to gain one — wrong.
- Fewest conflicts first? Tempting, but constructible counterexamples defeat it too.
Two of these failures are easy to picture. Earliest-start picks the long bar that blocks the whole timeline; shortest-job picks the short middle bar that displaces both of its neighbors.
The rule that works is earliest finish time first: repeatedly pick the compatible activity that finishes soonest.3 The intuition: finishing early frees the hall as soon as possible, leaving the most room for everything that follows. This is the crux of interval scheduling.
- 1sort activities so that
- 2earliest finish is safe
- 3last activity added to
- 4for to do
- 5if thenstarts after finishes
- 6
- 7
- 8return
After the one-time sort by finish time, a single linear scan does the rest: work, for total, dominated entirely by the sort. If the finish times arrive already sorted, the selection itself is linear.
Run the scan on the instance above. Sorting the seven activities by finish time gives the order . The scan keeps a single number, , the finish time of the last accepted activity, and admits the next activity exactly when its start is at least .
| Step | Activity | before | ? | Action | |
|---|---|---|---|---|---|
| 1 | — | — | accept, | ||
| 2 | ? no | reject | |||
| 3 | ? yes | accept, | |||
| 4 | ? no | reject | |||
| 5 | ? yes | accept, | |||
| 6 | ? yes | accept, | |||
| 7 | ? no | reject |
The scan accepts , the four-activity optimum drawn earlier. Each rejection happens because the candidate starts before the hall is free again; each acceptance advances to the new, later finish. The figure below traces the same run, marking every activity as accepted (blue) or rejected (struck through) in finish-time order.
Correctness by the exchange argument
The usual proof technique for greedy algorithms is the exchange argument: take any optimal solution, and show you can transform it, swapping one of its choices for the greedy choice, without making it worse. Since the result is no worse, it is still optimal, and it now agrees with greedy on the first choice. That establishes the greedy-choice property; optimal substructure then finishes the job by induction.
The picture of the swap is the whole argument in one image. Activity slides in where was, finishing at least as early, so nothing downstream can break.
With the greedy-choice lemma in hand, optimal substructure completes the proof by induction.
This two-step shape, (1) an exchange argument for the greedy-choice property and (2) induction via optimal substructure, is the template for every greedy correctness proof in this course, Huffman codes and minimum spanning trees included.
When greedy fails: the 0/1 knapsack
Greedy does not always work; the standard counterexample is the knapsack problem. We have a knapsack of capacity and items, item having weight and value . We want the most valuable load that fits.
In the fractional knapsack, we may take any fraction of an item. Here greed works perfectly: sort by value density , and greedily fill with the densest item, taking a fraction of the last one to top off the capacity exactly.4 An exchange argument proves it: any optimal solution that takes less of a denser item and more of a sparser one can be nudged toward the greedy choice without losing value.
Run the density rule concretely. Take capacity and three items, already listed in decreasing density:
| Item | Weight | Value | Density |
|---|---|---|---|
| 1 | 10 | 60 | 6.0 |
| 2 | 20 | 100 | 5.0 |
| 3 | 30 | 120 | 4.0 |
Greedy takes item whole (using of , value ), then item whole (using of , value ), then only a fraction of item : of its units fit, so it takes of it for more value. The load is worth , and the capacity is filled exactly. No division of these items into the sack does better, because every unit of weight we spend goes on the densest value still available — the moment a fraction of item replaces any unit already taken, the total can only drop.
In the 0/1 knapsack, each item is all-or-nothing: take it whole or leave it. And here the same density rule collapses. Consider and:
| Item | Weight | Value | Density |
|---|---|---|---|
| 1 | 6 | 12 | 2.0 |
| 2 | 5 | 9 | 1.8 |
| 3 | 5 | 9 | 1.8 |
Greedy by density grabs item (value , weight ), then cannot fit either remaining item, since both need weight but only is left. It returns value . Yet items and together weigh exactly and are worth . Greedy is far from optimal.
This is where the boundary between greedy and dynamic programming falls. The 0/1 knapsack has optimal substructure but lacks the greedy-choice property, so it needs DP, which considers both alternatives (take item or skip it) rather than committing to one. The fractional version restores the greedy-choice property because a fraction can always absorb the leftover capacity exactly, leaving no stranded space.
When is greed good? A glimpse of matroids
For a large family of problems there is a theorem of the form greedy is optimal exactly when…
, and its language is the
matroid.
A matroid is a pair built from a finite ground set and a family
of independent
subsets, satisfying two axioms:
- Heredity. If and , then . (Subsets of independent sets are independent.)
- Exchange. If and , then some element has . (A smaller independent set can always be grown using an element of a larger one.)
The forests of a graph form a matroid: subsets of a forest are forests, and a smaller forest can always borrow an edge from a larger one without making a cycle.
The headline result is due to Rado and Edmonds.
This theorem is why Kruskal's minimum spanning tree algorithm, which greedily adds the cheapest edge that creates no cycle, is correct: it is greedy on the graphic matroid. Activity selection, too, can be cast as greedy on a matroid.
Matroids do not cover every successful greedy algorithm; Huffman coding, our next lesson, falls outside the theory. But they explain a large class and sometimes reduce the correctness question to a checkable condition. We will not develop the theory further here; the exchange axiom that defines it is the same exchange idea used in our correctness proofs.
A recipe for greedy algorithms
Drawing the standard references together, the workflow is always the same:
- Cast the problem as a sequence of choices, where each choice leaves a smaller subproblem of the same kind.
- Guess a greedy rule — the locally optimal choice. Beware: the obvious rule is often wrong (recall the failed activity-selection rules).
- Prove the greedy-choice property with an exchange argument: any optimal solution can be transformed to contain the greedy choice.
- Prove optimal substructure and combine, by induction, into a full proof.
If steps 3 and 4 go through, the result is a correct, usually fast, usually simple algorithm. If they do not, use dynamic programming instead.
When greedy is only approximately optimal
CLRS frames greedy as a route to exact optima, and this lesson has kept to that: activity selection and the fractional knapsack are solved to optimality, or greed is abandoned. But the greedy method also serves as an approximation algorithm — a fast heuristic that is provably close to optimal even when finding the true optimum is intractable.
Set cover and the guarantee. Given a universe of elements and a family of sets, set cover asks for the fewest sets whose union is everything. It is NP-hard, so no efficient exact algorithm is expected. The natural greedy rule — repeatedly take the set covering the most still-uncovered elements — returns a cover using at most times as many sets as the optimum.6 The factor is tight: Dinur and Steurer (2014) proved that no polynomial-time algorithm beats unless , so greedy is essentially the best possible approximation.7 The same logarithmic greedy bound governs its twin, vertex cover by the maximum-degree rule, which is why set-cover-shaped problems (facility placement, feature selection, test-suite minimization) are usually attacked greedily first.
Online greedy and the competitive ratio. When the input arrives one piece at a time and each decision is irrevocable — an online problem — greedy is often the only option, and its quality is measured by the competitive ratio, the worst-case ratio of the online cost to the best offline (all-knowing) cost. The canonical case is caching / paging: on a cache miss, which page do you evict? Sleator and Tarjan (1985) showed that any deterministic online eviction policy is at best -competitive for a cache of size , and that the greedy-flavored Least-Recently-Used achieves that optimal , while their competitive analysis framework became the standard one for online algorithms.8 Greedy, in short, is both a route to exact optima and the natural — sometimes provably optimal — strategy when the input is revealed online.
Takeaways
- A greedy algorithm makes the locally optimal choice at each step and never reconsiders. It is fast and simple, when it is correct.
- Correctness needs two properties: the greedy-choice property (some optimal solution contains the greedy choice) and optimal substructure (what remains is the same problem, smaller).
- Activity selection by earliest finish time is the canonical win; its proof is the template exchange argument plus induction. Cost: , all in the sort.
- The 0/1 knapsack is the canonical failure: it lacks the greedy-choice property, so greed strands capacity and needs dynamic programming instead. Its fractional cousin restores the property and yields to greed.
- Matroids characterize a broad class where greedy is provably optimal (Kruskal's MST among them), a formalization of the exchange argument itself.
Footnotes
- Erickson, Ch. 4 — Greedy Algorithms: the warning that most greedy strategies are wrong and must be proved correct, not merely tested. ↩
- CLRS, Ch. 16 — Greedy Algorithms (§16.2): the greedy-choice property as one of the two ingredients licensing a greedy algorithm. ↩
- CLRS, Ch. 16 — Greedy Algorithms (§16.1): the activity-selection problem solved by repeatedly choosing the earliest-finishing compatible activity. ↩
- Skiena, §1.4 & §5 — Heuristics; Weighted Graph Algorithms: the fractional knapsack solved greedily by value density. ↩
- CLRS, Ch. 16 — Greedy Algorithms (§16.4): the Rado–Edmonds theorem that greedy yields a maximum-weight independent set exactly when the structure is a matroid. ↩
- CLRS, Ch. 35 — Approximation Algorithms (§35.3): the greedy set-cover algorithm and its proof of an approximation ratio. The original analysis is Johnson, D. S. (1974),
Approximation algorithms for combinatorial problems,
J. Computer and System Sciences 9(3), 256–278. ↩ - Dinur, I. & Steurer, D. (2014),
Analytical approach to parallel repetition,
STOC 2014, 624–633 — establishes that set cover cannot be approximated to better than in polynomial time unless , matching the greedy bound. ↩ - Sleator, D. D. & Tarjan, R. E. (1985),
Amortized efficiency of list update and paging rules,
Communications of the ACM 28(2), 202–208 — introduces competitive analysis and proves LRU is -competitive for a size- cache, the best possible for a deterministic policy. ↩
╌╌ END ╌╌