Skip to content
ΣDSA Patterns
Menu
Language

Pattern #21

Greedy

Recommended

Make 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.

Step 1 of 8
2
3
1
1
4

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

  1. State the local rule in one sentence.
  2. Sort or maintain a running best if needed.
  3. Scan once applying the rule; track failure conditions.
  4. Sanity-check with a tiny counterexample attempt.

Template

Same skeleton in TypeScript, Python, and C#. Adapt the invariant; keep the structure.

Greedy · Template
/** 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;
}
#StatusProblemTypeDone
  1. 1#45 Jump Game IIGuide
  2. 2#55 Jump GameGuide
  3. 3#134 Gas StationGuide
  4. 4#435 Non-overlapping IntervalsGuide
  5. 5#621 Task SchedulerGuide
  6. 6#763 Partition LabelsGuide