Greedy Algorithms
Make the best-looking move now, never undo it, and prove it can't hurt.
01 · why it exists
Why this exists, and the weight it carries
since1956–1971
The greedy method
Joseph Kruskal; Richard Rado; David Gale; Jack Edmonds
Greedy rules were in use before anyone could say when they work. Kruskal's 1956 minimum spanning tree adds the cheapest safe edge, again and again. Rado (1957), Gale (1968) and Edmonds (1971) found the clean answer for one big family of problems: "take the best remaining item that still fits" is optimal for every choice of weights exactly when the structure is a matroid. Edmonds' paper "Matroids and the greedy algorithm" is the classic reference. For everyday interview problems, you prove each greedy rule by hand instead: exchange argument or stays ahead.
the problem it solvedKnowing in advance when "always take the best remaining item" is guaranteed to be optimal, instead of hoping.
its jobs today
- Compression: Huffman coding merges the two rarest symbols first; DEFLATE (gzip, PNG) is built on it.
- Networks and maps: Kruskal's and Prim's spanning trees and Dijkstra's shortest paths are greedy algorithms.
- Schedulers: shortest-job-first and earliest-deadline-first pick the next task by one simple rule.
the weight it carries
Illustrative: put 1 lakh (10⁵) jobs in the best order. Trying every order means 10⁵! orders, which is hopeless. Greedy sorts once, about 10⁵ × log₂ 10⁵ ≈ 10⁵ × 17 = 1.7 million comparisons, then makes one pass.
without it
Many scheduling and selection problems would need DP or brute force: O(n²) or worse, where one sort and one pass would do.
when · why · how
- when
- A choice exists that is always safe, whatever comes later, and you can say why in one line.
- why
- One sort + one pass: O(n log n), instead of DP's O(n²) or brute force's 2ⁿ. The price: it is simply wrong without a proof.
- how
- Sort with
Arrays.sort(or keep aPriorityQueue/TreeMapwhen the best choice changes as you go), then one loop with a few variables of state.
since?
Proving greedy: exchange argument & stays ahead
These are proof styles, not inventions. Kleinberg and Tardos's textbook Algorithm Design (2005) uses them as section titles: "The Greedy Algorithm Stays Ahead" and "An Exchange Argument".
its jobs today
- Interviews: the one-line proof is what turns "I think greedy works" into an answer the interviewer can accept.
- Engineering: justifying a policy before you ship it, e.g. that shortest-job-first really minimises the average wait.
the weight it carries
Illustrative: 3 downloads of 10, 2 and 1 minutes. Biggest first: finish times 10, 12, 13, total 35 minutes of waiting. Smallest first: 1, 3, 13, total 17. Each swap of a neighbouring bigger-before-smaller pair saves exactly (bigger − smaller) minutes.
without it
A greedy answer without a proof is a guess. It can pass the examples and fail the hidden tests (coins {1, 3, 4}).
when · why · how
- when
- Right after you find a greedy rule, before you write any code.
- why
- Thirty seconds of argument separates a correct O(n log n) answer from a fast wrong one. Trying 2–3 tiny counter-examples costs even less.
- how
- Exchange: "take any best answer, swap its first differing choice for mine; still valid, no worse." Stays ahead: "after k steps, my
reach/ count / end time is at least as good as anyone's."
since?
Furthest reach (BFS on a line without a queue)
A classic interview technique with no single documented inventor. Jump Game II is BFS where every level is a contiguous range, so two integers replace the queue.
its jobs today
- Range coverage: picking the fewest clips or taps to cover [0, T] (LC 1024, LC 1326) uses the same "extend the reach, count when you cross the boundary" loop.
- BFS levels without a queue: whenever the reachable positions form one block,
endandfarthestreplace a queue of up to n entries.
the weight it carries
Illustrative: 10⁴ indices with jumps up to 10⁵. Plain recursion can explore exponentially many paths. DP over indices: up to 10⁴ × 10⁴ = 10⁸ steps. Furthest reach: 10⁴ steps and one int.
without it
Jump-style problems fall back to an O(n²) DP, or a BFS queue holding up to n indices.
when · why · how
- when
- Each position on a line tells you how far you can go next.
- why
- The reachable set is always one prefix, so its right edge is all you need: O(n) time, O(1) space.
- how
reach = Math.max(reach, i + nums[i]); fail wheni > reach. For the fewest jumps, addendand count a jump wheni == end.
since1970–2005
Change-making: where greedy breaks
S. K. Chang & A. Gill; Dexter Kozen & Shmuel Zaks; David Pearson
In 1970 Chang and Gill studied paying an amount with the fewest coins, and gave a test for when the simple biggest-coin-first rule is safe for a given coin set. Kozen and Zaks (1994) sharpened it: if greedy fails at all, the smallest failing amount is below the sum of the two biggest coins. Pearson (2005) gave a polynomial-time test that works for any coin system. Coin systems where greedy is always right are called canonical.
the problem it solvedKnowing when the cashier's rule "biggest coin first" is guaranteed to use the fewest coins, and catching coin sets where it isn't.
its jobs today
- Cash counters and vending machines: for ₹1, 2, 5, 10, 20, 50, 100, 200, 500, biggest-first always gives the fewest pieces (this chapter's Java checks every amount up to ₹3,000 against DP). The RBI's list also has the 50-paise coin and the ₹2000 note (still legal tender); the same Java check shows the system stays canonical with them, up to ₹10,000.
- Interview signal: "minimum coins" with arbitrary values (LC 322) is DP, not greedy. {1, 3, 4} at 6 is the counter-example to quote.
the weight it carries
Illustrative: amount 6 with coins {1, 3, 4}. Greedy: 4 + 1 + 1 = 3 coins. Optimal: 3 + 3 = 2 coins, so greedy uses 50% more. DP costs amount × coins steps: 6 × 3 = 18 here, and 10⁴ × 10 = 10⁵ for a big case.
without it
You'd ship biggest-first for a coin set like {1, 7, 10} and pay 14 as 10 + 1 + 1 + 1 + 1 (5 coins) instead of 7 + 7 (2).
when · why · how
- when
- Any "fewest items to reach a total" problem. Check whether the values are canonical before trusting greedy.
- why
- Greedy is O(k log k) for k coin values; DP is O(amount × k) but always right.
- how
GreedyCoins.greedyCoinssorts and walks from the biggest;DpCoins.minCoinsfillsdp[a] = min(dp[a - c] + 1). Compare them on small amounts to hunt for a counter-example.
02 · plain english
The idea in 30 seconds
A greedy algorithm builds the answer one step at a time. Each step takes the choice that looks best right now, and never undoes it.
It is usually one sort plus one pass: fast and short. But it is only correct when you can argue that the local best choice never blocks the best overall answer.
So greedy is two skills: spotting the safe choice, and proving it safe (or breaking it with a tiny counter-example and switching to DP).
picture this
Your download manager has five files queued on one connection. To make the average wait smallest, start the smallest file first. If a big file ever runs just before a smaller one, swap them: the small one finishes earlier, and the pair still ends at the same moment. Every such swap helps, so shortest-first wins. That swap is the exchange argument, the proof behind most greedy answers.
03 · remember
What you must know
- Greedy choice property: some best answer starts with the greedy choice. Optimal substructure: after that choice, what's left is a smaller copy of the same problem. You need both.
- Exchange argument: take any best answer. Swap its first choice that differs from greedy's for the greedy one. Show it's still valid and no worse. Repeat, and the best answer becomes the greedy answer.
- Greedy stays ahead: show that after every step, greedy's state is at least as good as anyone else's. Jump Game's
reachis never behind any other sequence of jumps. - Greedy can be wrong. Coins {1, 3, 4}, amount 6: biggest-first pays 4+1+1 (3 coins), but 3+3 is 2. When no proof works, or a tiny input breaks it, use DP.
- Furthest reach: in Jump Game the reachable indices always form a prefix [0..reach], so one integer replaces a whole search. Jump Game II counts BFS levels with two integers.
- Restart past a failure: in Gas Station, if the tank goes negative at i, no start in [start..i] can work, so jump straight to i + 1. One pass.
- Keep a range of possibilities: when a choice is unknown (a
*in LC 678), track the smallest and largest possible state instead of trying every choice. - Filter, then combine: in Merge Triplets, anything that overshoots the target is useless forever, and everything else is harmless to merge.
- Two passes for two-sided rules: Candy satisfies "more than the left neighbour" in one pass and "more than the right" in another, then takes the max.
- Forced choices: in Hand of Straights the smallest card must start a group, because nothing smaller is left to come before it.
- Typical cost: O(n) for the pass, O(n log n) if you sort first. Intervals (next chapter) are greedy's biggest family.
04 · see it
Play with it in 3D
Press Space to play, ←/→ to step, drag to move, ? for all shortcuts. Try your own input.
When greedy fails: biggest coin first
Try coins 1, 3, 4 with amount 6. Then try 1, 2, 5, 10, where greedy happens to be right.
Jump Game: one number of state
Only the furthest reachable index matters. If `i` ever passes it, you're stuck.
Gas Station: restart past a failure
When the tank goes negative, every start so far is ruled out at once. `total` decides whether any start works.
Valid Parenthesis String: a range instead of a guess
The green cells are every open count still possible. A `*` widens the range; `)` and `(` shift it.
Partition Labels: stretch to the last index
Each letter drags the piece's end to its last occurrence. When `i` reaches `end`, cut.
05 · cost
Time & space, explained
| Time | Extra space | why | |
|---|---|---|---|
| Try every jump (recursion) | O(2ⁿ) | O(n) | Paths multiply at every index, and the same index is solved again and again. The stack is up to n deep. |
| DP: can you finish from index i? | O(n²) | O(n) | Each index may scan up to n later indices. One boolean per index. |
| Greedy furthest reach | O(n) | O(1) | One pass and one integer: the reachable indices are always a prefix. |
| Time | Extra space | why | |
|---|---|---|---|
| Fewest jumps as BFS levels (LC 45) | O(n) | O(1) | end and farthest replace a queue, because every level is one contiguous range. |
| Restart after a negative prefix (LC 134) | O(n) | O(1) | Each station adds its gain to tank and total once. |
| Filter, then combine (LC 1899) | O(n) | O(1) | One look per triplet and three booleans. |
| Stretch to the last index (LC 763) | O(n) | O(1) | Two passes; last[26] has a fixed size whatever n is. |
| Range of possibilities (LC 678) | O(n) | O(1) | Two ints, lo and hi, updated once per character. |
| Two passes (LC 135) | O(n) | O(n) | One candies array, filled left to right and then right to left. |
| Smallest card starts a run (LC 846) | O(n log n) | O(n) | Every card is counted and consumed once, at O(log n) per TreeMap call. |
| Shortest job first | O(n log n) | O(n) | The sort dominates; the copy keeps the caller's array untouched. |
| Time | Extra space | why | |
|---|---|---|---|
| Biggest coin first | O(k log k) | O(k) | Sort the k values, then one division per value. Fast, but only right for canonical coin systems. |
| DP over every amount | O(A · k) | O(A) | Each amount 1..A tries every coin once. Always right. |
06 · java
Raw vs Collections Framework
The greedy template: sort, then one pass
class ShortestFirst { /** Jobs run one after another from time 0. Returns the smallest possible sum of finish times. */ static long totalFinishTime(int[] durations) { int[] jobs = durations.clone(); // don't reorder the caller's array Arrays.sort(jobs); // greedy rule: shortest job first long clock = 0, total = 0; // long: 10^5 jobs x 10^4 minutes overflows int for (int d : jobs) { clock += d; // this job finishes at `clock` total += clock; } return total; }}- Sort by the key that makes the safe choice obvious, then make one decision per item with a few variables of state.
Arrays.sort(int[])sorts primitives with a dual-pivot quicksort: O(n log n) on average, no boxing.durations.clone()first: sorting in place would reorder the caller's array behind their back.- Sums of times grow fast. 10⁵ jobs of 10⁴ minutes add up to about 5 × 10¹³, far past
int's 2.1 × 10⁹, soclockandtotalarelong.
When greedy fails: biggest coin vs DP
class GreedyCoins { /** "Biggest coin first". Correct for {1, 2, 5, 10, ...}; WRONG for coin sets like {1, 3, 4}. */ static int greedyCoins(int[] coins, int amount) { int[] sorted = coins.clone(); Arrays.sort(sorted); int count = 0; for (int i = sorted.length - 1; i >= 0 && amount > 0; i--) { int take = amount / sorted[i]; // as many of this coin as fit count += take; amount -= take * sorted[i]; } return amount == 0 ? count : -1; // -1: greedy got stuck }}class DpCoins { /** Fewest coins for every amount 0..amount: tries every coin at every step, so it can't be fooled. */ static int minCoins(int[] coins, int amount) { int[] dp = new int[amount + 1]; // dp[a] = fewest coins that pay exactly a Arrays.fill(dp, Integer.MAX_VALUE); dp[0] = 0; for (int a = 1; a <= amount; a++) { for (int c : coins) { if (c <= a && dp[a - c] != Integer.MAX_VALUE) { dp[a] = Math.min(dp[a], dp[a - c] + 1); } } } return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount]; }}- Biggest-first is right for canonical coin systems. The rupee system ₹1, 2, 5, 10, 20, 50, 100, 200, 500 is one:
GreedyBasics.javachecks every amount up to ₹3,000 against the DP. - It is wrong for {1, 3, 4} at amount 6, and it gets stuck for {3, 5} at amount 9 (taking 5 leaves 4, which 3 can't pay).
- The DP is the safe fallback:
dp[a] = min(dp[a - c] + 1)over every coin c. LC 322 Coin Change is exactly this.
Forced choices: sorted array + HashMap vs TreeMap
class Solution { public boolean isNStraightHand(int[] hand, int groupSize) { if (hand.length % groupSize != 0) return false; int[] cards = hand.clone(); Arrays.sort(cards); // smallest card first, once Map<Integer, Integer> count = new HashMap<>(); for (int c : cards) count.merge(c, 1, Integer::sum); for (int c : cards) { if (count.get(c) == 0) continue; // already used inside an earlier run for (int k = 0; k < groupSize; k++) { // c must START a run: c, c+1, ..., c+groupSize-1 int have = count.getOrDefault(c + k, 0); if (have == 0) return false; // gap in the run count.put(c + k, have - 1); } } return true; }}class Solution { public boolean isNStraightHand(int[] hand, int groupSize) { if (hand.length % groupSize != 0) return false; TreeMap<Integer, Integer> count = new TreeMap<>(); for (int c : hand) count.merge(c, 1, Integer::sum); while (!count.isEmpty()) { int first = count.firstKey(); // smallest card MUST start a group for (int k = 0; k < groupSize; k++) { int card = first + k; Integer have = count.get(card); if (have == null) return false; // gap in the run if (have == 1) count.remove(card); else count.put(card, have - 1); } } return true; }}TreeMapis a red-black tree:firstKey(),get,putandremoveare O(log n), and it always knows the smallest key.count.merge(c, 1, Integer::sum)adds one to a count in a single call, inserting 1 if the key is new.- Sorting once and walking the sorted array gives the same "smallest first" order with a plain
HashMap. Same O(n log n), fewer tree operations.
Uncertain choices: a range vs two stacks
class Solution { public boolean checkValidString(String s) { int lo = 0, hi = 0; // fewest and most '(' that could still be open for (char c : s.toCharArray()) { if (c == '(') { lo++; hi++; } else if (c == ')') { lo--; hi--; } else { // '*': ')' lowers lo, '(' raises hi lo--; hi++; } if (hi < 0) return false; // too many ')' even if every '*' is '(' lo = Math.max(lo, 0); // a count below 0 is never a real choice } return lo == 0; // some choice closes every '(' }}class Solution { public boolean checkValidString(String s) { Deque<Integer> opens = new ArrayDeque<>(), stars = new ArrayDeque<>(); // indices for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') opens.push(i); else if (c == '*') stars.push(i); else if (!opens.isEmpty()) opens.pop(); // a real '(' closes it first else if (!stars.isEmpty()) stars.pop(); // otherwise a '*' plays '(' else return false; } while (!opens.isEmpty()) { // leftover '(' need a '*' AFTER them if (stars.isEmpty() || stars.pop() < opens.pop()) return false; } return true; }}- The range version keeps two ints and never decides what a star is. O(1) space.
- The stack version stores indices in
ArrayDeques (push/popare O(1)). It does decide: each ')' uses a real '(' first, then a star. - At the end, a leftover '(' needs a star that comes after it. That's why the stacks hold indices, not characters.
| call | does | cost |
|---|---|---|
Arrays.sort(int[] a) | Sort primitives (dual-pivot quicksort) | O(n log n) |
Math.max(a, b) / Math.min(a, b) | Update reach, farthest, a clamp or a candy count | O(1) |
Arrays.fill(a, 1) | Give every child one candy to start | O(n) |
new TreeMap<Integer, Integer>() | Counts kept in key order (red-black tree) | O(1) to build |
map.merge(k, 1, Integer::sum) | Add one to a count, inserting 1 if absent | O(log n) TreeMap · O(1) avg HashMap |
treeMap.firstKey() | Smallest key still present | O(log n) |
map.getOrDefault(k, 0) | Read a count that may be missing | O(1) average (HashMap) |
Deque<Integer> st = new ArrayDeque<>() | Stack of indices: push, pop, isEmpty | O(1) per op |
Can you reach the end? Fewest jumps?
→ Two or three ints: reach, end, farthest
Reachable indices form a prefix, and BFS levels are ranges.
A circular route with a running balance
→ tank + total, restart at i + 1
A failed prefix rules out every start inside it; total says if any start works.
The smallest remaining item must be used next
→ TreeMap (or sort once + HashMap)
firstKey() is O(log n); sorting once is faster in practice.
A wildcard that can mean several things
→ A range [lo, hi] of possible states
Covers every choice at once with O(1) space.
Rules from both neighbours
→ Two passes over one int[]
Each pass fixes one direction; max keeps both.
No proof, or a 3-element counter-example breaks it
→ Dynamic programming
DP tries every choice, so a locally good move can't fool it.
07 · recognise
Spot the pattern
"Can you reach the end?" / "fewest jumps"
Furthest reach; BFS levels without a queue
Circular route with a running balance
Gas Station: restart after any prefix that goes negative
Constraints from both neighbours (left and right)
Two passes, one per direction (Candy)
"Split into as many parts as possible" with a last-occurrence rule
Partition Labels: stretch the end to the last index
A wildcard like * that can be several things
Track the range of possible states (lo, hi)
"Combine with max (or min) any number of times"
Throw away anything that overshoots; the rest is harmless
"Split into groups of consecutive values"
The smallest value must start a group (TreeMap)
"Order jobs to minimise total or average waiting"
Shortest first, proved by an exchange argument
Coins or weights with arbitrary values, "minimum number"
Be suspicious of greedy. Try a counter-example, then use DP
08 · traps & tricks
Mistakes to avoid, tricks to use
traps
- Using greedy without a proof. Always try 2–3 tiny counter-examples first (coins {1, 3, 4}, amount 6).
- Jump Game II: looping to
i < ninstead ofi < n - 1. That adds one extra jump when you land exactly on the end. - Gas Station: forgetting the
total >= 0check. The restart trick finds a candidate, but only the total says whether any start works. - Candy: writing
candies[i] = candies[i + 1] + 1in the second pass withoutmax, which throws away the first pass's work. - Valid Parenthesis String: skipping the
hi < 0check or the clamplo = max(lo, 0). Each one alone gives wrong answers. - Summing waiting times in
int. 10⁵ jobs × 10⁴ minutes overflows; uselong. - Sorting the caller's array when they still need its order. Clone it first.
tricks
- Say the greedy rule and its one-line proof before coding. That proof is what the interviewer is grading.
- Bas itna yaad rakho: if you can't say why the choice is safe, it probably isn't. Write the DP; a correct slower answer beats a fast wrong one.
- Ask yourself: "What's my one variable of state?" (
reach,tank,lo/hi,end). Most greedy answers are 5–10 lines. - Edge cases to test: one element, all equal, strictly rising, strictly falling, zeros, and the answer sitting at the very end.
- Stuck between greedy and DP? Write the O(n²) DP first. It's often the clue to the greedy: watch which DP choice always wins.
09 · why & how
Questions you might be too shy to ask
How do I know a problem is greedy and not DP?
Look for a choice that is always safe, no matter what comes later. Then try to break it with tiny inputs (2–4 items). If every small test passes and you can say why the choice can't hurt, it's greedy. If one small input breaks it, the problem needs DP (or backtracking).
Greedy and DP both pick the best option. What's the actual difference?
DP compares every option, each with its future already solved, and then picks the best. Greedy picks one option by a simple rule and never looks at the other options' futures. Coins {1, 3, 4}, amount 6: DP checks 6 − 4, 6 − 3 and 6 − 1, and sees that 6 − 3 = 3 needs just one more coin. Greedy grabs the 4 and is stuck paying 1 + 1. That's why greedy needs a proof and DP doesn't.
What is an exchange argument, in plain words?
Take any optimal answer. Look at the first place it differs from the greedy answer. Swap in the greedy choice and show the result is still valid and no worse. After enough swaps, the optimal answer is the greedy answer, so greedy is optimal. For the download queue: if a bigger file runs just before a smaller one, swapping them saves exactly (bigger − smaller) minutes of total waiting.
What does "greedy stays ahead" mean?
Instead of swapping, you compare progress. Show that after every step, greedy's state is at least as good as any other solution's. In Jump Game, reach is the furthest any sequence of jumps could have got so far, so if greedy gets stuck, everyone does.
Most greedy answers start with a sort. How do I pick what to sort by?
Sort so the safe choice comes first. The "best" item is not always the biggest: it's the shortest job (waiting time), the smallest card (Hand of Straights), the furthest reach (Jump Game). Write down 2–3 candidate keys, test each on a tiny input, and keep the one you can defend with a swap. The next chapter, Intervals, is full of exactly this question: sort by start or by end?
How do I find a counter-example fast?
Keep inputs tiny (2–4 items) and try the shapes that fool greedy: one big item that blocks two medium ones (coins {1, 3, 4}, amount 6), equal values, all rising, all falling. Work out the true best answer by hand — with 3 items you can list every option. If greedy loses even once, stop: the problem needs DP or backtracking.
Why is Jump Game II greedy and not BFS?
It is BFS, just without a queue. All indices reachable with k jumps form one contiguous block (a level). end marks the edge of the current level, and farthest builds the next one. Reaching end means one more jump. Since the levels are contiguous ranges, two integers replace the queue.
Jump Game II: which index do I actually jump to? The one with the biggest number?
Not the biggest number — the biggest reach, i + nums[i]. In [3, 4, 1, 3, 1, 1, 1], from index 0 you can land on 1, 2 or 3. Index 1 has the biggest value (4) but reaches only index 5; index 3 reaches 3 + 3 = 6, the end. Biggest value costs 3 jumps, biggest reach costs 2. The level loop never names the index — farthest quietly tracks the best reach for you.
In Gas Station, why can we skip every start between the old start and i?
Say you start at s and the tank first goes negative at i. Pick any start k between s + 1 and i. Starting fresh at k, your tank at k is 0. Coming from s, you reached k with a tank of 0 or more. So from k onwards the fresh tank is never fuller than the old one — and the old one already ran dry at i. So none of s..i works, and the next candidate is i + 1.
Gas Station: why does total >= 0 guarantee the last candidate really works?
The restarts cut the circle into failed pieces (each sums to less than 0), then the last stretch from the candidate to the end, which never went negative and leaves a tank of T ≥ 0. Keep driving from the end into the failed pieces: inside a piece, the tank only drops below its level at that piece's start at the piece's last station. So the lowest it can ever be is T + (all failed pieces) = total ≥ 0. It never runs dry, and you get back to the candidate.
Why does biggest-coin-first work for rupees but not for {1, 3, 4}?
Coin systems where greedy is always right are called canonical. ₹1, 2, 5, 10, 20, 50, 100, 200, 500 is canonical: this chapter's Java checks every amount up to ₹3,000 against DP. {1, 3, 4} isn't: at 6, taking the 4 leaves 2, which costs two 1s. Kozen and Zaks proved that if greedy fails at all, it already fails below the sum of the two biggest coins, so a short check finds the counter-example.
If greedy is so fast, why learn DP at all?
Because greedy is only correct when one locally best choice is always safe (the greedy choice property). That set is small and easy to get wrong. DP is the safe general tool. Greedy is the shortcut you take once you've proved it's safe.
Do I have to write a formal proof in an interview?
No. One or two sentences is enough: name the choice, then say why swapping it into any best answer can't hurt, or why your state is never behind. The interviewer wants to hear that you checked, not a page of maths.
10 · practice
Interview problems
Every problem has brute → better → optimal solutions in Java, with complexity and a dry run.
- #55
- #45
- #134
- #1899Merge Triplets to Form Target TripletMediumGoogle
- #763Partition LabelsMediumAmazonGoogleMeta
- #678
- #846Hand of StraightsMediumGoogleAmazon
- #135CandyHardAmazonMicrosoftGoogle
Also practise this here
Each problem has one home page in the course; these use this chapter's idea too. The note says what to look for.
- #322Coin ChangeMediumin Dynamic Programming
Where biggest-coin-first breaks: the DP answer to this chapter's counter-example.
- #621
- #121Best Time to Buy and Sell StockEasyin Arrays & Strings
A one-pass greedy: remember the cheapest price so far.
11 · revise
The whole chapter on one screen
8 cards, about a minute. Read them the night before an interview, or right after the chapter to lock it in.
- what it is
Greedy = take the best-looking choice now and never undo it. Fast (one sort + one pass), but only right with a proof.
- use it when
One choice is always safe: furthest reach, restart after a failure, smallest card first. Can't say why in one line? Suspect DP.
- template
Sort by the key that makes the choice obvious → one loop → a few variables of state (
reach,tank,lo/hi). - cost
Usually O(n) for the pass, O(n log n) with a sort. DP for the same problem is often O(n²); brute force is 2ⁿ.
- trap
Coins {1, 3, 4}, amount 6: biggest-first pays 4+1+1 (3 coins), but 3+3 is 2. Test 2–3 tiny inputs before trusting greedy.
- trap
Gas Station: the restart finds a candidate, but only
total >= 0says a start exists. Skip it and you return a wrong index. - pro tip
Prove it out loud: exchange (swap any best answer's choice for mine, no worse) or stays ahead (my
reachis never behind). - pro tip
Unknown choices? Track a range. LC 678 keeps
lo/hiopen counts instead of trying all 3ᵏ meanings of the stars.
12 · recall
Flip, remember, repeat
Which two properties make a greedy algorithm correct?
Question 1: Which two properties make a greedy algorithm correct?
13 · check yourself
Quick quiz
Coins {1, 3, 4}, amount 6. What does biggest-coin-first return, and what is optimal?
Jobs of 4, 1 and 3 minutes run one after another. Which order gives the smallest total of finish times?
Jump Game: nums = [1, 0, 2]. At i = 1, reach = 1. What happens at i = 2?
Jump Game II on [2, 3, 1, 1, 4]: at i = 0, end = 0 and farthest becomes 2. What happens?
Gas Station: the tank first goes negative at station 4 with start = 1. Which start do you try next?
Valid Parenthesis String: after reading "(*", what is the range [lo, hi] of possible open counts?
Candy: ratings [1, 2, 2]. What is the minimum total?
Which problem is safely solved by greedy?
14 · learn more
A second teacher, if you want one
- ▶ playlistGreedy Algorithm Playlist | Language Independent Series ↗Striver (take U forward) · EnglishThirteen short greedy problems from easy to hard: jump game, job sequencing, N meetings, interval problems, platforms and candy.
- ▶ video3. Greedy Method - Introduction ↗Abdul Bari · EnglishWhat the greedy method is and when it applies: the theory behind 'make the best-looking move now, never look back'.
- ▤ bookGreedy Algorithms ↗Jeff Erickson, Algorithms (UIUC) · EnglishA free textbook chapter that proves greedy choices correct with exchange arguments. Read it when you want the 'why', not just the 'how'.