greedy-intervals dp ⏱️ 10 min read • Updated 2026-10-19

Greedy vs Dynamic Programming

The Cashier Coin Trap and Proving the Greedy Choice Property

How to tell when making the best local choice right now is globally optimal, versus when choices interact and require dynamic programming.

⚡ The Discriminating Question

"Does making the locally optimal choice right now guarantee you will never regret it later, or can an early choice paint you into a suboptimal corner?"

Ask this single question during the first two minutes of reading the problem prompt. The answer decides your fundamental pattern.

💡In Plain Words: The Chai Stall Cashier and the Special Token Dilemma

A chai stall cashier makes change for customers. With standard Indian currency coins (Rs 1, Rs 2, Rs 5, Rs 10), a greedy strategy works every single time: always hand back the largest denomination possible. If change is Rs 7, you give Rs 5 and Rs 2. You never get a suboptimal coin count. But imagine the stall owner introduces promotional tokens worth Rs 1, Rs 3, and Rs 4. A customer needs Rs 6 in change. The greedy cashier grabs the largest coin first: Rs 4. That leaves Rs 2, which requires two Rs 1 coins (4 + 1 + 1 = 3 coins). But another customer hands over two Rs 3 tokens: exactly Rs 6 in only 2 coins (3 + 3 = 2)! The greedy cashier got painted into a corner because picking the biggest coin early locked out the optimal pair.

Key Takeaway: Use Greedy only when you can mathematically prove the Greedy Choice Property: an optimal solution contains the local greedy choice, and subproblems never interact backward. When choices interact, subproblems overlap and you must use Dynamic Programming to evaluate competing options.

When to Choose Which Pattern

Greedy Algorithms

Option A
Choose this when:
  • ✓The problem has the greedy choice property: a global optimum can be reached by selecting the locally best choice at each step without backtracking.
  • ✓Optimal substructure: an optimal solution to the problem contains optimal solutions to subproblems.
  • ✓Decisions are irreversible: once you make a choice, you never need to reconsider.
  • ✓Sorting or scanning the input lets you lock in decisions one by one.
Time ComplexityO(N) or O(N log N) if sorting is required
Auxiliary SpaceO(1) auxiliary memory

Dynamic Programming

Option B
Choose this when:
  • ✓Subproblems overlap: solving subproblem A requires answers to smaller subproblems that are also needed by subproblem B.
  • ✓Choices interact: taking an item or coin now limits future decisions, so multiple paths must be compared.
  • ✓Optimization over combinations: finding min, max, or count across non-canonical values.
  • ✓Greedy fails on counterexamples.
Time ComplexityO(N * Target) or O(N^2)
Auxiliary SpaceO(Target) or O(N * Target) memo table

Side-by-Side Worked Examples

Compare concrete implementations side by side to see how the code structure diverges.

Jump Game(LC 55)

LeetCode ↗

Maintain max_reachable index. As you iterate through index i, if i > max_reachable, you are stranded. Otherwise, update max_reachable = max(max_reachable, i + nums[i]). You never care which specific jump brought you to an index, only the maximum reach boundary. This local greedy extension guarantees finding whether the end is reachable.

Python 3LC 55
def canJump(nums: list[int]) -> bool:
    max_reachable = 0
    for i, jump in enumerate(nums):
        if i > max_reachable:
            return False
        max_reachable = max(max_reachable, i + jump)
    return True

Coin Change(LC 322)

LeetCode ↗

Let dp[a] be the minimum coins needed to make amount a. For each amount from 1 to target, try every available coin denomination: dp[a] = min(dp[a - coin] + 1) for coin <= a. Because arbitrary denominations lack the greedy choice property, DP explores all overlapping choices systematically.

Python 3LC 322
def coinChange(coins: list[int], amount: int) -> int:
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a:
                dp[a] = min(dp[a], dp[a - c] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

The Decision Matrix

Choice Reversibility

Greedy Algorithms

Permanent, never reconsidered or backtracked

Dynamic Programming

Considers all valid choices and takes the minimum or maximum

Subproblem Overlap

Greedy Algorithms

Subproblems do not overlap; only one branch is followed

Dynamic Programming

Subproblems overlap heavily; results are memoized or tabulated

Runtime Complexity

Greedy Algorithms

Usually O(N) or O(N log N)

Dynamic Programming

Polynomial O(N * W), O(N^2), or pseudo-polynomial

Proof Requirement

Greedy Algorithms

Requires formal exchange argument or matroids proof

Dynamic Programming

Requires defining state variables and recurrence relation

⚠️

Where Candidates Go Wrong (Top Traps)

✕

Assuming Greedy works because it passes small examples on paper

Why it fails in interviews: Greedy is seductive because it feels intuitive. But without mathematical proof (like an exchange argument), subtle edge cases will fail in production or hidden tests.
✓The Senior Engineer Fix: If you cannot articulate why the local choice never closes off the global optimum, write the DP recurrence first.
✕

Using 2D DP when a greedy single-pass reachability scan works

Why it fails in interviews: Candidates over-engineer Jump Game or interval scheduling into O(N^2) DP tables, exceeding time limits.
✓The Senior Engineer Fix: Ask: do I actually care about the history of steps, or only the outer boundary reached? Boundary-only problems are often greedy.
✕

Confusing Fractional Knapsack with 0/1 Knapsack

Why it fails in interviews: Fractional knapsack (items can be divided) is solvable by greedy sort by value-to-weight ratio. 0/1 Knapsack (items are discrete) is NP-hard and requires DP.
✓The Senior Engineer Fix: Verify whether items can be split. If items must be taken whole, greedy by unit value will fail.

Related Walkthroughs in our DSA Course

Explore step-by-step solutions with 4-language code flaps (Java, C#, TS, Python) and visual memory dry runs.

problem

Non-overlapping Intervals (Greedy Interval Scheduling)

View in DSA Path→
problem

Partition Equal Subset Sum (0/1 Knapsack DP)

View in DSA Path→
problem

Longest Increasing Subsequence (DP State Evolution)

View in DSA Path→
⚖️What Did I Give Up By Choosing This? (The Tradeoff)

"Greedy delivers O(N) speed and O(1) memory, but gives up safety unless the greedy choice property is mathematically proven. Dynamic Programming guarantees global optimality across interacting choices, but trades away memory for state tables."

Practice Real Indian Hiring Loops

See the exact problems asked at Flipkart, Swiggy, Razorpay, PhonePe, and Amazon with verified candidate reports and round structures.