Pattern 15 of 20
Greedy
Make the locally best choice and prove it never hurts the final answer.
When to use it
- Choosing the most items, the fewest steps or the furthest reach
- A sort order makes the right choice obvious
- Dynamic programming works but feels heavier than needed
The idea
At each step take the option that keeps the most possibilities open. The hard part is the argument: show that swapping any optimal solution's choice for the greedy one is never worse.
Typical cost O(n) or O(n log n) with a sort.
How it works
A greedy algorithm makes the locally best choice at each step and never revisits it. When it works it is the simplest and fastest solution available, usually a sort followed by one pass. The hard part is not the code; it is knowing the local choice is safe.
The standard justification is an exchange argument: take any optimal solution that disagrees with your first greedy choice, and show you can swap in the greedy choice without making it worse. If that always works, greedy is optimal.
Greedy often hides behind a running quantity. In jump games you track the farthest reachable index; in gas-station circuits you reset the start whenever the running fuel goes negative; in maximum subarray you drop a prefix the moment its sum turns negative.
Be suspicious when small counterexamples come easily. Coin change with arbitrary coin values is the classic trap: picking the largest coin first fails, and the problem needs DP. Always test the greedy rule on a few tricky inputs before trusting it.
How to attack it
- 1State the greedy rule in one sentence (always take the earliest end, the largest gap, the cheapest next).
- 2Try to break it with two or three small counterexamples.
- 3Sort by the key the rule depends on, if any.
- 4Maintain the running quantity that the rule reads in one pass.
- 5Sketch the exchange argument, or fall back to DP if it fails.
Template
A skeleton to adapt, not a solution to paste. Write it from memory a few times.
def can_reach_end(jumps):
# Track the farthest index reachable so far.
farthest = 0
for i, step in enumerate(jumps):
if i > farthest:
return False # stuck before reaching i
farthest = max(farthest, i + step)
return True
def circuit_start(gain, cost):
# If the total is negative no start works; otherwise reset on deficit.
if sum(gain) < sum(cost):
return -1
start, tank = 0, 0
for i in range(len(gain)):
tank += gain[i] - cost[i]
if tank < 0: # no station in start..i can be the start
start, tank = i + 1, 0
return start
def max_subarray(nums):
best = cur = nums[0]
for x in nums[1:]:
cur = max(x, cur + x) # drop a negative prefix
best = max(best, cur)
return bestVariants
- Sort, then sweep
- Order by deadline, end time, ratio or size, then take items while they fit.
- Farthest reach
- Jump games and minimum jumps: extend a frontier and count how many times you must cross it.
- Reset on deficit
- Kadane's maximum subarray and the gas-station circuit restart whenever the running value goes negative.
- Two-pass constraints
- Left-to-right then right-to-left passes satisfy neighbor rules, such as handing out candies by rating.
- Greedy with a heap
- When the best local choice changes as you go, keep candidates in a heap and take the top each step.
Pitfalls
- Trusting a greedy rule without testing a counterexample.
- Sorting by the wrong key (start time instead of end time for maximum non-overlapping intervals).
- Using greedy for coin change with arbitrary coin values.
- Initializing a running best to 0 when all values may be negative.
- Missing the global feasibility check (total gas versus total cost) before trusting the local reset.
What it costs
| Operation | Cost |
|---|---|
| Single pass with a running value | O(n) time, O(1) space |
| Sort then sweep | O(n log n) |
| Greedy with a heap | O(n log n) |
| DP alternative when greedy fails | Usually O(n²) or O(n · target) |
30 Greedy problems
Easiest first. Problems marked Free can be solved without Pro.
- 1Snacks for the Field TripFreeEasy
- 2Exact Change at the Ticket BoothFreeEasy
- 3Saplings Along the FenceFreeEasy
- 4Gather Tokens on One SquareEasy
- 5Load the Delivery TruckEasy
- 6Split the Signal Into Balanced PiecesEasy
- 7Pair Up the PlayersEasy
- 8Largest Triangular PenEasy
- 9Move Students to DesksEasy
- 10Can You Reach the Last StoneMedium
- 11Fewest Leaps to the Far BankMedium
- 12Courier Loop StartMedium
- 13Deal the Cards Into RunsMedium
- 14Blend to the Target MixMedium
- 15Cut the Log Into Exclusive SegmentsMedium
- 16Brackets With WildcardsMedium
- 17Fly Interviewees to Two OfficesMedium
- 18Make Badge Numbers UniqueMedium
- 19Broken Dial CalculatorMedium
- 20Make Every Letter Count DistinctMedium
- 21Most Rounds Won in the DuelMedium
- 22Spend Tokens for PointsMedium
- 23Biggest Number From the PiecesMedium
- 24Rebuild the Photo LineMedium
- 25Bonus Tokens for the TeamHard
- 26Flip Switches in Fixed BlocksHard
- 27Patch the Stamp CollectionHard
- 28Fewest Refuels on the HighwayHard
- 29Most Workshops Before DeadlinesHard
- 30Strongest Project TeamHard
Solve them in the browser, in Python or JavaScript.