Greedy method and exchange argument
The greedy method: build a solution by always making the choice that looks best now. The two properties that make it correct (greedy-choice property and optimal substructure), the exchange argument and greedy stays ahead as proof methods, the shortest-processing-time rule as a first proof, the coin-change example that shows greedy failing for some coin systems, and a list of the greedy algorithms of the syllabus.
Why it exists
Many optimisation problems ask for the best selection out of an astronomical number of possibilities. A greedy algorithm avoids the search: at each step it takes the choice that looks best right now and never reconsiders. Greedy algorithms are usually the simplest and fastest (often , dominated by a sort), but they are correct only for problems with the right structure, and the main skill tested in exams is telling whether greedy works and why. This page gives the criteria and the proof method; the next pages apply them to scheduling, knapsack and coding, and later pages to spanning trees and shortest paths.
Prerequisites
You need to be able to count the running time of a loop with a sort (analysing loops).
Precise definitions
Greedy algorithm. It builds a solution step by step. At each step it picks, among the options currently allowed, the one that is best by a fixed local rule (largest, earliest, cheapest, ...), commits to it, and shrinks the problem.
Greedy-choice property. There is an optimal solution that contains the greedy choice. (So committing to it loses nothing.)
Optimal substructure. After the greedy choice is made, what remains is a smaller problem of the same kind, and an optimal solution of the whole contains an optimal solution of the smaller problem.
A greedy algorithm is correct when both properties hold. Dynamic programming also needs optimal substructure but not the greedy-choice property: it tries all choices (dynamic programming).
Exchange argument (the standard proof). Take any optimal solution . Show that can be changed, one step at a time, into the greedy solution without getting worse: swap a part of for the greedy choice and show the value does not decrease. Since each swap keeps optimality, is optimal.
Greedy stays ahead (the other method). Show by induction that after every step the greedy partial solution is at least as good as the partial solution of any other algorithm, by a measure that implies the final claim.
A counterexample is the only way to show that a greedy rule is wrong, and one suffices.
How it works
A first proof: shortest processing time first
jobs with processing times are done one after another on one machine. Job finishes at its completion time (the sum of the processing times up to and including it). Goal: minimise the total (equivalently the average) completion time. Rule: shortest job first.
Exchange argument. Take any order and look at two adjacent jobs then with (a longer job before a shorter one), starting at time . Their completion times are and , with sum . After swapping them they are and , with sum . The difference is : the swap makes the total smaller, and no other job is affected (the pair finishes at the same time in both orders). So any order that has a longer job directly before a shorter one can be improved; the only order with no such pair is the sorted one, which is therefore optimal. (An independent check tried every order of hundreds of random job sets: the sorted order always gave the minimum.)
The algorithm is a sort: . Another rule with the same style of proof: to minimise the maximum lateness (completion time minus deadline), do the jobs in order of earliest deadline first.
When greedy fails: making change
Pay an amount with as few coins as possible. Greedy rule: take the largest coin that fits, repeat. The program compares greedy with the exact optimum (computed by dynamic programming) for three coin systems.
#include <stdio.h>
/* coins[] is in decreasing order; the greedy method takes as many of the largest coin as possible, then the next, ... */
static int greedy(const int coins[], int k, int amount) {
int count = 0;
for (int i = 0; i < k; i++) {
count += amount / coins[i];
amount %= coins[i];
}
return count;
}
/* the fewest coins, by dynamic programming over all amounts up to the given one */
static int optimal(const int coins[], int k, int amount) {
int best[256];
best[0] = 0;
for (int a = 1; a <= amount; a++) {
best[a] = 1 << 20;
for (int i = 0; i < k; i++)
if (coins[i] <= a && best[a - coins[i]] + 1 < best[a]) best[a] = best[a - coins[i]] + 1;
}
return best[amount];
}
int main(void) {
int a[4] = {25, 10, 5, 1}, b[3] = {4, 3, 1}, c[3] = {10, 6, 1};
int amounts_a[4] = {30, 41, 63, 99}, amounts_b[5] = {5, 6, 7, 8, 9}, amounts_c[2] = {12, 30};
for (int t = 0; t < 4; t++) printf("A %2d greedy %d optimal %d\n", amounts_a[t], greedy(a, 4, amounts_a[t]), optimal(a, 4, amounts_a[t]));
for (int t = 0; t < 5; t++) printf("B %2d greedy %d optimal %d\n", amounts_b[t], greedy(b, 3, amounts_b[t]), optimal(b, 3, amounts_b[t]));
for (int t = 0; t < 2; t++) printf("C %2d greedy %d optimal %d\n", amounts_c[t], greedy(c, 3, amounts_c[t]), optimal(c, 3, amounts_c[t]));
int bad_a = 0, bad_b = 0, bad_c = 0;
for (int x = 1; x <= 200; x++) {
if (greedy(a, 4, x) != optimal(a, 4, x)) bad_a++;
if (greedy(b, 3, x) != optimal(b, 3, x)) bad_b++;
if (greedy(c, 3, x) != optimal(c, 3, x)) bad_c++;
}
printf("amounts 1 to 200 where greedy is not optimal: A %d, B %d, C %d\n", bad_a, bad_b, bad_c);
return 0;
}A 30 greedy 2 optimal 2
A 41 greedy 4 optimal 4
A 63 greedy 6 optimal 6
A 99 greedy 9 optimal 9
B 5 greedy 2 optimal 2
B 6 greedy 3 optimal 2
B 7 greedy 2 optimal 2
B 8 greedy 2 optimal 2
B 9 greedy 3 optimal 3
C 12 greedy 3 optimal 2
C 30 greedy 3 optimal 3
amounts 1 to 200 where greedy is not optimal: A 0, B 49, C 114Greedy change-making against the optimum: start
Computed by a script, not typed| coins and amount | greedy coins | fewest coins possible | verdict |
|---|---|---|---|
| coins {1, 5, 10, 25}, amount 30 | |||
| coins {1, 5, 10, 25}, amount 41 | |||
| coins {1, 5, 10, 25}, amount 63 | |||
| coins {1, 5, 10, 25}, amount 99 | |||
| coins {1, 3, 4}, amount 5 | |||
| coins {1, 3, 4}, amount 6 | |||
| coins {1, 3, 4}, amount 7 | |||
| coins {1, 3, 4}, amount 8 | |||
| coins {1, 3, 4}, amount 9 | |||
| coins {1, 6, 10}, amount 12 | |||
| coins {1, 6, 10}, amount 30 |
Step 0
Greedy takes the largest coin that fits, repeatedly. For coins 1, 5, 10, 25 it is optimal for every amount tested (1 to 200); for 1, 3, 4 and for 1, 6, 10 it fails for 49 and 114 of the amounts 1 to 200.
- System A, : greedy is optimal for every amount (none of fails; it was also checked up to ). Systems like this one are called canonical. The coins , powers of one base, are also canonical.
- System B, : for the amount greedy takes , three coins, but is two. The first failures are . The greedy choice "take the " is not part of any optimal solution of : the greedy-choice property fails.
- System C, : for , greedy takes but is better.
So the same rule is correct for one set of inputs and wrong for another. A proof (or a known theorem) is needed each time; a few examples that work prove nothing.
Where greedy works in the syllabus
| Problem | Greedy rule | Page |
|---|---|---|
| Activity selection | earliest finish time first | activity selection |
| Fractional knapsack | highest value per unit weight first | activity selection and fractional knapsack |
| Job sequencing with deadlines | highest profit first, latest free slot | same page |
| Huffman coding | merge the two least frequent | Huffman coding |
| Minimum spanning tree | cheapest safe edge (Kruskal, Prim) | spanning trees |
| Shortest paths, non-negative edges | closest unvisited vertex (Dijkstra) | Dijkstra |
Where greedy fails (and dynamic programming or search is needed): 0/1 knapsack, shortest paths with negative edges, general coin systems, travelling salesman.
Worked examples
EX 1Shortest job first
EasyProcessing times . In the given order the completion times are : total . In the sorted order they are : total , average . Any other order lies between: the sorted order is the minimum, and the longest-first order is the maximum ().
EX 2Greedy change that is not optimal
EasyCoins , amount : greedy (three coins), optimum (two coins). A GATE question may give the denominations and ask for the amounts on which greedy is optimal or the number of coins greedy uses; always compare with the optimum before answering "greedy works".
EX 3An exchange argument in words
MediumClaim: choosing the activity that finishes first is safe. Let be an optimal set of activities and the activity that finishes earliest of all. If does not contain , replace the first activity of by : since finishes no later than that activity, it overlaps nothing that came after it in , so the new set is still compatible and has the same size. So an optimal solution containing exists: the greedy-choice property holds (next page for the full algorithm).
EX 4Greedy by the wrong key
MediumMinimising total completion time by taking the job with the largest processing time first is the worst order, not the best; taking the job with the earliest deadline is right for lateness but not for total completion time. Choosing the greedy key is half of the problem: the proof tells which key.
EX 5True or false about greedy
GATE level(a) Greedy always gives an optimal solution: false (coin change with ). (b) A greedy algorithm for fractional knapsack is optimal, for 0/1 knapsack it is not: true (next page). (c) Dijkstra's algorithm is greedy and fails with negative edge weights: true. (d) The running time of a greedy algorithm is dominated by sorting or by a priority queue, typically : true for the algorithms of this syllabus. (e) Greedy and dynamic programming both use optimal substructure; only greedy also needs the greedy-choice property: true.
Cheat box
Cheat box
- Greedy: commit to the locally best choice, never reconsider. Correct iff greedy-choice property (an optimal solution contains the greedy choice) and optimal substructure.
- Proof: exchange argument (turn any optimal solution into the greedy one without loss) or greedy stays ahead (induction).
- One counterexample disproves a greedy rule; examples never prove it.
- Shortest processing time first minimises total completion time; earliest deadline first minimises maximum lateness.
- Coin change: greedy optimal for and powers of a base; fails for (amount ).
- Typical cost: sort or heap, .
- Works: activity selection, fractional knapsack, Huffman, Kruskal, Prim, Dijkstra (non-negative). Fails: 0/1 knapsack, negative-edge shortest paths.
Traps and GATE patterns
Connections
Builds on
Unlocks
Across subjects
No cross-subject links yet.
The method is applied in activity selection and fractional knapsack, Huffman coding, spanning trees and Dijkstra's algorithm. When greedy fails the usual tool is dynamic programming. Sorting costs come from the sorting pages and loop counting from analysing loops.
PYQs
3 previous year questions from your book. I re-solved each one myself (0 by running or simulating, 3 by reasoning only); the book's key is shown next to my answer. All PYQs
Consider the following table: Algorithms Design Paradigms P Kruskal i Divide and Conquer Q Quicksort ii Greedy R Floyd- Warshall iii Dynamic Programming
- (a)P-(ii), Q-(iii), R-(i)
- (b)P-(iii), Q-(i), R-(ii)
- (c)P-(ii), Q-(i), R-(iii)
- (d)P-(i), Q-(ii), R-(iii)
Given below are some algorithms, and some algorithm design paradigms. List - I P. Dijkstra's Shortest Path Q. Floyd-Warshall algorithm to compute all pairs shortest path R. Binary search on a sorted array S. Backtracking search on a graph List – II i. Divide and Conquer ii. Dynamic Programming iii. Greedy design iv. Depth-first search v. Breadth-first search Match the above algorithms on the left to the corresponding design paradigm they follow.
- (a)P-i, Q-iii, R-i, S-v.
- (b)P-iii, Q-iii, R-i, S-v.
- (c)P-iii, Q-ii, R-i, S-iv.
- (d)P-iii, Q-ii, R-i, S-v.
Match the following: (P) Prim's algorithm for minimum spanning tree (i) Backtracking (Q) Floyd-Warshall algorithm for all pairs shortest paths (ii) Greedy method (R) Mergesort (iii) Dynamic programming (S) Hamiltonian circuit (iv) Divide and conquer
- (a)P-iii, Q-ii, R-iv, S-i
- (b)P-i, Q-ii, R-iv, S-iii
- (c)P-ii, Q-iii, R-iv, S-i
- (d)P-ii, Q-i, R-iii, S-iv
Self-check
Question 1
Coins , amount : how many coins does greedy use and what is the optimum?
Show answerHide
Greedy: , four coins. Optimum: , three coins.
Question 2
In which order should jobs be processed to minimise the total completion time?
Show answerHide
Shortest processing time first (exchange argument: a longer job directly before a shorter one can be swapped with an improvement).
Question 3
What two properties make a greedy algorithm correct?
Show answerHide
The greedy-choice property and optimal substructure.
Question 4
How do you show that a greedy rule is wrong?
Show answerHide
Give one instance on which it does not produce an optimal solution.
Revision card
One-screen revision
- Greedy = commit to the best local choice; needs greedy-choice property + optimal substructure.
- Proofs: exchange argument, greedy stays ahead. Counterexample disproves.
- SPT minimises total completion time; EDF minimises maximum lateness.
- Coin change: canonical systems yes, no.
- Greedy: activity selection, fractional knapsack, Huffman, MST, Dijkstra. Not: 0/1 knapsack.
References
- ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 16 Greedy Algorithms (16.1 activity selection, 16.2 elements of the greedy strategy)
- ·Kleinberg and Tardos, Algorithm Design, Chapter 4 Greedy Algorithms (4.1 interval scheduling, 4.2 minimizing lateness)
- ·Dasgupta, Papadimitriou, Vazirani, Algorithms, Chapter 5 Greedy algorithms
Verification
The shortest-processing-time rule was checked against every permutation of 300 random job sets (total completion time) and earliest-deadline-first against every permutation (maximum lateness). The coin-change program on this page was compiled and run and its results recomputed by an independent Python implementation of greedy and of dynamic programming for every amount up to 200; greedy was also confirmed optimal for the systems {1, 5, 10, 25}, {1, 3, 9, 27} and {1, 2, 5, 10, 20, 50, 100} for every amount up to 1000, and not optimal for {1, 3, 4} (first failures 6, 10, 14) and {1, 6, 10}. Coin systems made of the powers of one base (bases 2, 3, 4, 5 and 10, six coins each) were confirmed greedy-optimal for every amount up to 2000; the general statement is not proved here. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)