Overview
A greedy algorithm builds a solution step by step, always making the choice that looks best right now, and never reconsiders it. When it works it is usually the simplest and fastest solution: often a sort followed by one pass.
The hard part is knowing when greedy is correct. It works when the problem has the greedy-choice property (a locally best choice is part of some optimal solution) and optimal substructure. You justify it with an exchange argument: show that any optimal solution can be changed to include the greedy choice without getting worse. If you cannot, use DP.
With 25, 10, 5, and 1 cent coins, always handing over the largest coin that fits gives the fewest coins. But with coins 1, 3, and 4, the same greedy rule fails for 6 (4 + 1 + 1 instead of 3 + 3). Greedy is powerful, but only when the structure of the problem guarantees it.
When to use it
- Scheduling or selecting intervals: earliest finish, fewest overlaps.
- Assigning resources: match smallest to smallest, largest to largest.
- Reachability with maximum reach tracking (jump game, gas station).
- Building the lexicographically smallest or largest result.
- The problem has a clean exchange argument; otherwise consider DP.
Problem patterns it solves
Recognize it when: maximum non-overlapping intervals, arrows, meetings.
- 435. Non-overlapping Intervals
- 452. Minimum Number of Arrows to Burst Balloons
- 646. Maximum Length of Pair Chain
Recognize it when: can you reach the end; minimum jumps.
- 55. Jump Game
- 45. Jump Game II
- 1326. Minimum Number of Taps to Open to Water a Garden
Recognize it when: pair people, cookies, boats, workers to jobs.
- 455. Assign Cookies
- 881. Boats to Save People
- 826. Most Profit Assigning Work
- 1029. Two City Scheduling
Recognize it when: if the running total drops below zero, restart after this point.
- 134. Gas Station
- 53. Maximum Subarray (Kadane)
- 1014. Best Sightseeing Pair
Recognize it when: each element must satisfy rules relative to both neighbors.
- 135. Candy
- 406. Queue Reconstruction by Height
Recognize it when: repeatedly take the most urgent / largest / cheapest.
- 621. Task Scheduler
- 1167. Minimum Cost to Connect Sticks
- 630. Course Schedule III
- 502. IPO
Where it is used in real software
ZIP, PNG, and JPEG compress data with Huffman codes, built by greedily merging the two least frequent symbols.
Dijkstra's shortest path and Prim's and Kruskal's minimum spanning trees are greedy algorithms with proofs of correctness.
Operating systems and job schedulers use greedy rules such as shortest job first or earliest deadline first.
Belady's optimal cache eviction (evict the item used farthest in the future) is greedy; LRU approximates it.
Key terms
- Greedy choice property
- A locally optimal choice can be extended to a globally optimal solution.
- Exchange argument
- Show swapping part of an optimal solution for the greedy choice does not make it worse.
- Optimal substructure
- After the greedy choice, the rest is a smaller instance of the same problem.
- Counterexample
- A small input where greedy fails, proving you need another approach.
Designing and verifying a greedy solution
- 1Guess the greedy rule
Earliest end, smallest first, largest first, best ratio, farthest reach.
- 2Try to break it
Test 3 to 5 small hand examples, including tricky ones. One counterexample means switch to DP.
- 3Argue exchange
Take any optimal solution; replace its first choice with the greedy one and show it stays valid and no worse.
- 4Sort if needed
Many greedy rules need sorted input: O(n log n).
- 5Scan once
Apply the rule while maintaining a small state: last end, reach, balance.
Gas station (134)
gas = [1, 2, 3, 4, 5], cost = [3, 4, 5, 1, 2]
| i | gas - cost | tank | Action | start |
|---|---|---|---|---|
| 0 | -2 | -2 | tank < 0: restart after 0 | 1 |
| 1 | -2 | -2 | tank < 0: restart after 1 | 2 |
| 2 | -2 | -2 | tank < 0: restart after 2 | 3 |
| 3 | 3 | 3 | keep going | 3 |
| 4 | 3 | 6 | keep going | 3 |
NOWi: 0 | gas - cost: -2 | tank: -2 | Action: tank < 0: restart after 0 | start: 1
Total gas (15) >= total cost (15), so a solution exists, and it starts at 3. If you run out between start and i, no station in that range can be a valid start, because each of them would arrive at i with even less gas.
Implementation
function canJump(nums) { let reach = 0; for (let i = 0; i < nums.length; i++) { if (i > reach) return false; // stuck before i reach = Math.max(reach, i + nums[i]); } return true;} function canCompleteCircuit(gas, cost) { let total = 0, tank = 0, start = 0; for (let i = 0; i < gas.length; i++) { const diff = gas[i] - cost[i]; total += diff; tank += diff; if (tank < 0) { start = i + 1; // nothing in [start, i] can work tank = 0; } } return total >= 0 ? start : -1;} // 135. Candy: two passes, each fixes one neighbor constraintfunction candy(ratings) { const n = ratings.length; const give = new Array(n).fill(1); for (let i = 1; i < n; i++) if (ratings[i] > ratings[i - 1]) give[i] = give[i - 1] + 1; for (let i = n - 2; i >= 0; i--) if (ratings[i] > ratings[i + 1]) give[i] = Math.max(give[i], give[i + 1] + 1); return give.reduce((a, b) => a + b, 0);} // 881. Boats to Save People: heaviest with lightest if possiblefunction numRescueBoats(people, limit) { people.sort((a, b) => a - b); let boats = 0, light = 0, heavy = people.length - 1; while (light <= heavy) { if (people[light] + people[heavy] <= limit) light++; heavy--; boats++; } return boats;}Complexity and performance
Most greedy solutions.
Reach or balance tracking.
Repeated best choice.
Trade-offs
Greedy is faster and simpler but only correct with the greedy-choice property. DP explores all options and is always correct for problems with optimal substructure, at higher cost.
In interviews, give a brief exchange argument or an intuitive invariant; interviewers often ask 'why is greedy correct here?'.
Variants and related techniques
Items can be split, so taking the best value/weight ratio first is optimal (unlike 0/1 knapsack).
Take items greedily but undo the worst one with a heap when a constraint breaks (Course Schedule III).
Build the smallest result with a monotonic stack (Remove K Digits).
Common mistakes
- Applying greedy without checking a counterexample.
Fix: Always test small tricky inputs, like coins [1, 3, 4] for amount 6.
- Sorting by the wrong key.
Fix: Interval selection sorts by end, not start. Test both on an example.
- Single pass for two-sided constraints.
Fix: Candy needs a left pass and a right pass.
Interview questions
How do you prove a greedy algorithm is correct?
Use an exchange argument: take any optimal solution, show it can be transformed step by step to agree with the greedy choices without losing optimality. Or show the greedy choice keeps an invariant that guarantees the optimum.
Why does sorting by end time work for interval scheduling?
The interval that ends first leaves the most time for the rest. Swapping the first interval of any optimal schedule for the earliest-ending one keeps the schedule valid and the same size.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| 455. Assign Cookies | Easy | Sort and match. |
| 55. Jump Game | Medium | Max reach. |
| 134. Gas Station | Medium | Restart on negative balance. |
| 881. Boats to Save People | Medium | Two pointers + greedy. |
| 826. Most Profit Assigning Work | Medium | Sort both sides. |
| 135. Candy | Hard | Two passes. |