Dynamic Programming
Greedy Algorithms
Algorithm Comparison
Computer Science
Optimization Techniques

What is the difference between dynamic programming and greedy approach?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Dynamic programming and greedy algorithms both solve optimization problems, but they make decisions in very different ways. A greedy algorithm commits to the best-looking local choice at each step, while dynamic programming keeps track of multiple subproblem results so it can build a globally optimal answer.

The Core Difference

A greedy algorithm says, in effect, “take the best move right now and trust that it leads to the best overall solution.” That works only when the problem has the greedy-choice property.

Dynamic programming is more cautious. It breaks the problem into overlapping subproblems, solves each one, and reuses those results. This is appropriate when local choices can block the true optimum and the problem has both overlapping subproblems and optimal substructure.

The important practical question is not which technique is faster in theory. It is whether the problem’s structure justifies greedy commitment.

A Greedy Example That Works

Interval scheduling is a classic greedy problem. If the goal is to pick the maximum number of non-overlapping intervals, choosing the interval that finishes earliest is optimal.

python
1def max_non_overlapping(intervals):
2    intervals = sorted(intervals, key=lambda item: item[1])
3    chosen = []
4    current_end = float("-inf")
5
6    for start, end in intervals:
7        if start >= current_end:
8            chosen.append((start, end))
9            current_end = end
10
11    return chosen
12
13
14intervals = [(1, 4), (3, 5), (0, 6), (5, 7), (8, 9), (5, 9)]
15print(max_non_overlapping(intervals))

This works because the locally best choice, the earliest finishing interval, leaves the most room for future selections.

A Greedy Example That Fails

Coin change is a good counterexample. Suppose the coin values are 1, 3, and 4, and you want to make 6 using the fewest coins.

A greedy strategy picks 4 first, then 1, then 1, for a total of three coins. But the optimal answer is 3 + 3, which uses only two coins.

That is exactly the kind of problem where dynamic programming helps.

python
1def min_coins(amount, coins):
2    dp = [float("inf")] * (amount + 1)
3    dp[0] = 0
4
5    for value in range(1, amount + 1):
6        for coin in coins:
7            if coin <= value:
8                dp[value] = min(dp[value], dp[value - coin] + 1)
9
10    return dp[amount]
11
12
13print(min_coins(6, [1, 3, 4]))

The table records the best answer for every smaller amount, so the algorithm does not get trapped by an attractive early choice.

How to Recognize Dynamic Programming Problems

Dynamic programming is appropriate when two conditions are present.

First, the problem must have optimal substructure. That means the optimal solution can be assembled from optimal solutions to smaller parts.

Second, the subproblems must overlap. If the same smaller computations appear repeatedly, storing results avoids repeated work.

Fibonacci numbers are the usual teaching example, but real interview and production problems include edit distance, longest common subsequence, knapsack, matrix chain multiplication, and many resource-allocation problems.

DP often appears in two styles:

  • top-down memoization, where recursion stores computed answers
  • bottom-up tabulation, where a table is filled iteratively

Tradeoffs in Practice

Greedy algorithms are often shorter, faster, and easier to reason about once correctness is proven. They usually use less memory because they do not store a full subproblem table.

Dynamic programming is more general, but it costs more in state design and memory usage. You must define the subproblem, transition rule, base cases, and often the reconstruction logic for the final answer.

That extra complexity is justified when greedy choice is unsafe. A fast wrong answer is still wrong.

Common Pitfalls

The biggest pitfall is assuming that a problem is greedy just because a local choice feels intuitive. Many plausible greedy rules fail on carefully chosen counterexamples.

Another mistake is applying dynamic programming without checking for overlapping subproblems. If the smaller problems are all distinct, memoization adds overhead without much benefit.

Developers also confuse “works on my sample input” with a proof. Greedy algorithms demand correctness arguments. Without one, a passing test set may simply be missing the bad case.

In dynamic programming, weak state design is a common failure mode. If the state omits information that affects future choices, the recurrence will produce the wrong result even though the code looks systematic.

Summary

  • Greedy algorithms make the best-looking local choice and never revisit it.
  • Dynamic programming stores results for smaller overlapping subproblems to guarantee the global optimum when the recurrence is correct.
  • Greedy is usually simpler and lighter, but only valid when the greedy-choice property holds.
  • Dynamic programming is the safer choice when early local decisions can block the optimal answer.
  • The right question is not “Which technique is better?” but “What structure does this problem actually have?”

Course illustration
Course illustration

All Rights Reserved.