Pattern #21
Greedy
RecommendedMake the best local choice when you can prove it never ruins the global optimum.
When to use
After sorting or a clear priority, a single forward pass decides irrevocably and stays optimal (exchange argument).
Recognition cues
- Jump game / jump game II
- Gas station / task scheduler
- Sort then scan / earliest end first
Common pitfalls
- Greedy without a proof (counterexamples exist)
- Wrong sort key
- Confusing greedy with DP when future choices interact
90-second recognition drill
Which pattern fits best?
- Jump game / jump game II
- Gas station / task scheduler
- Sort then scan / earliest end first
Interactive
Mental model
A full worked walkthrough of the invariant. Pause, scrub the dots, or use ← →. Aim to narrate each step yourself.
far = 0
Jump Game: track the farthest index reachable so far.
How to think about it
Identify a score for each choice (farthest reach, earliest finish, largest gain). Sort or scan so the next pick is obvious. Prove that swapping any other pick for yours cannot improve the answer (exchange argument).
Template shapes
| Shape | Core move | Notes |
|---|---|---|
| Jump reach | Track farthest | Fail if i > far |
| Interval select | Earliest end first | Max non-overlap |
| Gas circuit | Track tank + start | Unique circuit if total ≥ 0 |
Complexity baseline
Often O(n log n) for sort + O(n) scan, or pure O(n).
From template to problem
- State the local rule in one sentence.
- Sort or maintain a running best if needed.
- Scan once applying the rule; track failure conditions.
- Sanity-check with a tiny counterexample attempt.
Template
Same skeleton in TypeScript, Python, and C#. Adapt the invariant; keep the structure.
/** Greedy template: Jump Game (farthest reach). Track far; fail if i > far. */
export function canJump(nums: number[]): boolean {
let far = 0;
for (let i = 0; i < nums.length; i++) {
if (i > far) return false;
far = Math.max(far, i + nums[i]!);
if (far >= nums.length - 1) return true;
}
return true;
}
/** Greedy template: Jump Game (farthest reach). Track far; fail if i > far. */
export function canJump(nums: number[]): boolean {
let far = 0;
for (let i = 0; i < nums.length; i++) {
if (i > far) return false;
far = Math.max(far, i + nums[i]!);
if (far >= nums.length - 1) return true;
}
return true;
}
- 1#45 Jump Game IIGuidemedium
- 2#55 Jump GameGuidemedium
- 3#134 Gas StationGuidemedium
- 4#435 Non-overlapping IntervalsGuidemedium
- 5#621 Task SchedulerGuidemedium
- 6#763 Partition LabelsGuidemedium