Part 7 · 1 chapters · ~8 min

Greedy Algorithms

The greedy-choice property and exchange arguments, interval scheduling, Huffman coding, Dijkstra and Prim as greedy algorithms, when greedy fails (with counterexamples), and greedy heuristics for hard problems.

14

When the locally best choice is globally best

A greedy algorithm makes the best-looking choice at each step and never reconsiders. It is correct only when the problem has the greedy-choice property, usually proven with an exchange argument: any optimal solution can be transformed, step by step, into the greedy one without getting worse.

code
// interval scheduling: the maximum number of non-overlapping meetings → sort by END time, take greedily
function maxMeetings(ms: [number, number][]): number {
  let count = 0, end = -Infinity;
  for (const [s, e] of [...ms].sort((x, y) => x[1] - y[1])) if (s >= end) { count++; end = e; }
  return count;
}
// sorting by START time or by shortest duration both fail on some inputs: the choice of greedy rule is everything
greedy worksgreedy fails
interval scheduling by earliest endcoin change with arbitrary denominations ({1, 3, 4})
Huffman coding (merge two rarest symbols)0/1 knapsack (taking best value-per-weight first)
Dijkstra with non-negative weightsDijkstra with negative weights
Kruskal and Prim for MSTtravelling salesman (nearest neighbour is only a heuristic)

For NP-hard problems (Theory of Computation, course 27), greedy algorithms are often used as heuristics: fast, good-enough answers without guarantees.