The Greedy paradigm is a general approach to problem solving. It involves making a series of myopic and irrevocable decisions which lead to the optimal solution.
This breaks down solving the problem into solving one problem repeatedly.
Thus we can solve the problem iteratively.
This makes it a powerful problem solving approach but the problem is that for most problems, the greedy approach does not produce the right answer.
Hence, proofs are core to the greedy paradigm: we need to be able to prove that the greedy approach leads to the correct answer.
Greedy algorithms usually share the following characteristics:
- Easy to devise (from an initial analysis of the problem)
- Easy to determine time complexity (usually sort + some constant time processing)
- Hard to prove correctness
If a greedy approach fails, then we have to turn to the other methods, namely divide and conquer or (at the worst-case) brute-force search of the solution space
Approach to proofs
The core analytic idea in the greedy paradigm is the idea of an optimal substructure:
In computer science, a problem is said to have optimal substructure if an optimal solution can be constructed from optimal solutions of its subproblems. This property is used to determine the usefulness of greedy algorithms for a problem.
Exchange Arguments
The other important idea for greedy algorithms is the exchange argument.
The goal of the exchange argument is to show that of the multiple optimal solutions, there exists one optimal solution that is reached by the greedy approach (i.e. greedy algorithms lead to an optimal solution).
There are multiple ways to write out an exchange argument. Here, we present a popular approach to an exchange argument, which gives an idea of how an exchange argument may be structured.
Using contradiction
The first approach to exchange arguments uses proof by contradiction. The assumption that we make (which we then try to contradict) is that there exists an optimal solution \(\sigma^*\) which performs better than the greedy solution \(\sigma\).
The end result we are aiming for is to show that the greedy solution performs better than the assumed optimal solution \(\sigma^*\), leading to a contradiction.
Here is how we set about writing out an exchange argument to follow this line of reasoning:
- Focus on the differences. Typically, you can isolate a simple example of this difference, such as one of the following:
- there is an element of O that is not in A and an element of A that is not in O, or
- there are 2 consecutive elements in O in a different order than they are in A (i.e. there is an inversion).
- Exchange to show that going from \(\sigma^*\) to \(\sigma\) will create a more optimal solution.
- Arrive at the contradiction. Hence, the optimal solution cannot be better than the greedy solution.
However, it is easy to trip up with exchange arguments. Here are some common pitfalls to avoid:
- Be careful about using proofs by contradiction starting with the assumption \(\sigma\neq\sigma^*\). Just because your greedy solution is not equal to the selected optimal solution does not mean that greedy is not optimal – there could be many optimal solutions, and your greedy one just isn’t the optimal solution you selected. So assuming \(\sigma\neq\sigma^*\) may not get you any contradiction at all, even if greedy works.
- You need to argue why the 2 elements you’re swapping even exist out of order, or exist in \(\sigma^*\) but not in \(\sigma\), etc.
- Remember you need to argue that multiple swaps can get you from your selected solution to greedy, as one single swap will usually not suffice.
- Make sure that any step you make (and not just the first one) doesn’t hurt the solution quality.
A simple illustrative case is the scheduling problem. The greedy approach picks the task that has the earliest deadline.
Suppose we have an optimal schedule (\(\sigma^*\)) that is different from the EDF schedule (\(\sigma\)).
- Look at the first position where (\(\sigma^*\)) and (\(\sigma\)) differ.
- At this position, (\(\sigma^*\)) schedules a job (\(J_i\)) with a later deadline before a job (\(J_j\)) with an earlier deadline.
- This creates an inversion: two consecutive jobs are in the wrong order relative to EDF.
Now, swap (\(J_i\)) and (\(J_j\)) in (\(\sigma^*\)).
- After the swap, (\(J_j\)) (earlier deadline) comes before (\(J_i\)).
- This exchange does not increase the maximum lateness:
- (\(J_j\)) finishes earlier, which can only reduce its lateness.
- (\(J_i\)) finishes later, but since its deadline is later than (\(J_j\))’s, its lateness does not increase beyond what it was before.
- The swap reduces the number of inversions.
By repeatedly applying this exchange, we can eliminate all inversions.
- Eventually, (\(\sigma^*\)) transforms into (\(\sigma\)), the EDF schedule.
- Since (\(\sigma^*\)) was assumed optimal, and we can transform it into EDF without worsening maximum lateness, EDF must also be optimal.
- Contradiction: there cannot exist a schedule strictly better than EDF.
Direct Proof
An exhcnage argument can also be presented as a direct proof where you assume that the greedy solution \(\sigma_G\) is better than an arbitrary solution \(\sigma\). Then, we can use the principle of an exchange argument to show that we can convert any solution \(\sigma\) to the greedy solution \(\sigma_G\) by performing exchanges that make the solution more optimal. Since the greedy solution is an improvement over every arbitrary solution, it can be shown to be the best solution.
Justifying Greedy
Here is how to show that a problem can be solved with a greedy algorithm:
- Cast the problem where we have to make a greedy choice. This leaves us with just one sub problem to solve.
- Prove (usually using an exchange argument) that there is always an optimal solution to the original problem that makes the greedy choice.
- Use optimal substructure (usually using proof by contradiction) to show that we can combine an optimal solution to the sub problem with the greedy choice to get an optimal solution to the original problem.
Pitfalls
Here are some issues that you might come across when trying to come up with greedy strategies:
- Ignoring feasibility constraints
- You show that swapping increases or preserves value, but forget that deadlines, capacities, or resource limits may be violated after the swap.
- Example: In scheduling problems, swapping jobs by profit doesn’t guarantee deadlines are still met.
- Assuming local optimality implies global optimality
- Just because one swap improves the situation doesn’t mean repeated swaps lead to the global optimum.
- Exchange arguments must prove that any optimal solution can be transformed into the greedy one without loss.
- Incomplete definition of the greedy solution
- If the greedy algorithm only produces an order but doesn’t specify how constraints are satisfied (like assigning slots), the exchange argument is proving something about an ill‑defined object.
- Overlooking tie-breaking subtleties
- When multiple elements have equal priority, the exchange argument must show that any tie-breaking choice leads to optimality, or else specify the correct tie-breaking rule.
- Not proving termination of exchanges
- You need to show that after a finite number of exchanges, the greedy solution is reached. Otherwise, the argument is circular.
- Confusing “no worse” with “always feasible”
- It’s not enough to show that swapping doesn’t reduce value; you must also show feasibility is preserved at every step.
Thinking about exchange arguments is an art. So there are a lot of mental models you might use to help you out.
Think of exchange arguments as a “repair process”:
- Start with an optimal solution.
- Whenever it deviates from greedy, “repair” it by swapping in the greedy choice.
- If every repair keeps feasibility and doesn’t reduce value, then the greedy solution is optimal.