Skip to content

Greedy Algorithms

A greedy algorithm makes the locally optimal choice at each step, hoping this leads to a globally Optimal solution. Unlike dynamic programming, greedy algorithms do not consider all possible Subproblems — they commit to a choice and never reconsider.

SignalTry Greedy First?
Problem has a matroid structureYes
Activity/resource scheduling with orderingYes
Huffman-like optimal prefix codingYes
Fractional version of a knapsack problemYes
MST or shortest path on non-negative weightsYes
0/1 knapsack, partition, edit distanceNo (use DP)
TSPNo (NP-hard)
Problem requires “try all possibilities” to verify correctnessProbably No

The exchange argument is the primary proof technique for greedy correctness. The idea: assume an Optimal solution differs from the greedy solution, then show we can exchange some element of the Optimal solution with the greedy choice without making the solution worse.

  1. Let GG be the greedy solution and OO be an optimal solution
  2. Find the first point where GG and OO differ
  3. Show that replacing the optimal”s choice with the greedy’s choice produces a solution OO' that is at least as good as OO
  4. Conclude that there exists an optimal solution that agrees with the greedy at this step
  5. By induction, the greedy solution is optimal

Given nn activities with start times sis_i and finish times fif_iSelect the maximum number of Non-overlapping activities.

Greedy: always pick the activity with the earliest finish time.

def activity_selection(activities):
"""
Maximum number of non-overlapping activities.
Greedy: sort by finish time, pick earliest finishing.
Time: O(n log n) for sorting
Space: O(1) (excluding input)
"""
sorted_activities = sorted(activities, key=lambda x: x[1])
count = 0
last_finish = float('-inf')
for start, finish in sorted_activities:
if start >= last_finish:
count += 1
last_finish = finish
return count

Exchange argument proof:

Let G={g1,g2,}G = \{g_1, g_2, \ldots\} be the greedy solution and O={o1,o2,}O = \{o_1, o_2, \ldots\} be an optimal Solution, both sorted by finish time. g1g_1 has the earliest finish time of all activities. Since o1o_1 also finishes before o2,o3,o_2, o_3, \ldotsWe have f(g1)f(o1)f(g_1) \le f(o_1). Replacing o1o_1 with g1g_1 in OO gives a valid solution (since g1g_1 finishes no later than o1o_1It does not overlap With o2o_2). The new solution has the same size as OO and starts with g1g_1. By induction, G=O|G| = |O|.