What Is Dynamic Programming?

Dynamic programming (DP) is one of the most powerful and frequently tested algorithm paradigms in computer science. At its core, DP is a technique for solving complex problems by breaking them down into overlapping subproblems and storing results to avoid redundant computation.

If you've ever solved a Fibonacci problem recursively and noticed your function re-computing the same values over and over, you've already seen the problem DP solves.

The Two Pillars: Memoization vs. Tabulation

There are two primary approaches to implementing dynamic programming:

  • Top-Down (Memoization): Start with the original problem, recurse into subproblems, and cache results as you go.
  • Bottom-Up (Tabulation): Build solutions to all subproblems from the smallest case upward, filling a table iteratively.

Both approaches yield the same results, but they differ in code style and sometimes in practical performance. Memoization is often more intuitive to write; tabulation is typically more memory-efficient.

Step-by-Step: Fibonacci With DP

The classic example to illustrate DP is computing Fibonacci numbers.

Naive Recursion (Exponential Time)

def fib(n):
    if n <= 1: return n
    return fib(n-1) + fib(n-2)

This runs in O(2ⁿ) time — catastrophically slow for large inputs.

Memoized Version (O(n) Time)

def fib(n, memo={}):
    if n in memo: return memo[n]
    if n <= 1: return n
    memo[n] = fib(n-1, memo) + fib(n-2, memo)
    return memo[n]

Tabulated Version (O(n) Time, O(n) Space)

def fib(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(2, n + 1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

Recognizing a DP Problem

Not every problem needs DP. Here's how to spot one:

  1. Optimal substructure: The optimal solution can be built from optimal solutions to subproblems.
  2. Overlapping subproblems: The same subproblems are solved multiple times in a naive recursive approach.

Common problem types that benefit from DP include: knapsack problems, coin change, longest common subsequence, shortest path in DAGs, and matrix chain multiplication.

Common DP Patterns to Learn

PatternExample Problems
Linear DPFibonacci, House Robber
Grid DPUnique Paths, Minimum Path Sum
Interval DPBurst Balloons, Matrix Chain
Knapsack DP0/1 Knapsack, Subset Sum
String DPLongest Common Subsequence, Edit Distance

Tips for Solving DP Problems

  • Define your state clearly — what does dp[i] represent?
  • Write the recurrence relation before coding.
  • Identify base cases and handle edge cases early.
  • Start with memoization if bottom-up feels unclear.
  • Optimize space only after correctness is confirmed.

Next Steps

Once you're comfortable with Fibonacci-style DP, move on to the 0/1 Knapsack problem and Longest Common Subsequence (LCS) — these two cover the vast majority of DP interview questions you'll encounter. Practice on LeetCode's "Dynamic Programming" tag, starting with Easy and Medium problems.