# How to Approach Dynamic Programming Problems in Coding Interviews: A 9-Step Framework

> Master dynamic programming problems in coding interviews. Learn a 9-step framework to identify sub-problems, define states, and implement memoization or tabulation for interview success.

- Repository: [Yangshun Tay/tech-interview-handbook](https://github.com/yangshun/tech-interview-handbook)
- Tags: how-to-guide
- Published: 2026-02-25

---

**To solve dynamic programming problems in interviews, identify problems with overlapping sub-problems and optimal substructure, define minimal state variables that capture sub-problems, formulate a recurrence relation, then implement using either top-down memoization or bottom-up tabulation while applying space compression when possible.**

Dynamic programming (DP) is a method for solving complex optimization problems by breaking them into simpler sub-problems. According to the [Tech Interview Handbook](https://github.com/yangshun/tech-interview-handbook), mastering DP requires a systematic workflow rather than memorizing solutions. This guide walks through the exact 9-step approach outlined in [`apps/website/contents/algorithms/dynamic-programming.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/dynamic-programming.md) to help you solve optimization problems confidently in technical interviews.

## Step 1: Identify DP Candidates

The first step is recognizing when dynamic programming applies. Look for problems asking for **"maximum/minimum"**, **"count the ways"**, **"best"**, or **"optimal"** solutions.

Key signal phrases include:
- **Sub-sequence**, **sub-array**, or **substring** operations
- **Grid** or **path** counting through matrices
- **Budget**, **knapsack**, or **partition** constraints
- **Optimization** under specific constraints

The handbook's *Essential questions* list serves as a sanity check. If you encounter problems resembling **[Climbing Stairs](https://leetcode.com/problems/climbing-stairs/)**, **[Coin Change](https://leetcode.com/problems/coin-change/)**, or **[House Robber](https://leetcode.com/problems/house-robber/)**, you are likely dealing with a DP problem.

## Step 2: Define the State

Once you identify a DP problem, define your **state**—a minimal set of variables that uniquely describe a sub-problem. Common state variables include:
- An index `i` representing position in an array or string
- Remaining capacity `c` for knapsack variants
- Row `r` and column `c` coordinates for grid-based problems

The state must be small enough to memoize efficiently yet expressive enough to capture the problem's progress. For example, in the Climbing Stairs problem, the state is simply the current step `i`.

## Step 3: Formulate the Recurrence

Express the answer for a given state in terms of answers to smaller states. This **recurrence relation** is the mathematical core of your solution.

Before coding, verify your recurrence with hand-drawn examples to avoid off-by-one errors. For Climbing Stairs, the recurrence is `dp(i) = dp(i-1) + dp(i-2)`, representing the sum of ways to reach the previous step and the step before that.

## Step 4: Pick a DP Style

Choose between two implementation approaches based on the problem structure:

**Top-down (Memoization)**: Write a recursive function that caches results in a hash map or array. This approach is intuitive when the recurrence naturally follows the problem definition.

**Bottom-up (Tabulation)**: Fill a table iteratively from base cases upward. This style avoids recursion depth limits and often allows better space optimization.

According to [`apps/website/contents/algorithms/dynamic-programming.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/dynamic-programming.md) (lines 35-36), you sometimes do not need to store the entire DP table—storing only the last two values suffices for many problems.

## Step 5: Initialize Base Cases

Populate the first row or column of your DP table, or seed the memoization cache with trivial answers. Base cases represent the simplest sub-problems that can be solved without recursion.

Examples include:
- `0` ways to reach a negative sum or invalid state
- `1` way to reach sum `0` (using no elements)
- Initial grid cells with boundary values

## Step 6: Iterate or Recurse

Execute the computation following your chosen style.

For **bottom-up**, loop in the proper order—typically forward for "prefix" problems and reverse for "suffix" problems. Ensure you access previously computed states in the correct sequence.

For **top-down**, implement the recursive function with memoization checks at the entry point. Monitor recursion depth to avoid exceeding language limits (Python recursion limits or JavaScript call-stack size).

## Step 7: Extract the Final Answer

The solution typically resides at the **target state** representing the original problem's parameters. Common extraction points include:
- `dp[n]` for the nth stair or position
- `dp[capacity]` for knapsack problems
- The bottom-right cell `dp[m][n]` for grid path problems

## Step 8: Optimize Space and Time

After achieving a working solution, optimize if time permits. If the recurrence uses only the last `k` states, replace the full table with a **rolling array** or constant variables.

For very large inputs, consider advanced techniques like **state compression** (bitmask DP) or **divide-and-conquer DP** (convex hull trick), though these appear less frequently in standard interviews.

## Step 9: Communicate Clearly

Before writing code, explain your **state definition**, **recurrence relation**, and **why it works** to the interviewer. Walk through a small example on the whiteboard or verbally. Discuss trade-offs explicitly: time complexity equals `O(n × states)` and space complexity equals `O(states)` or `O(1)` after compression.

## Practical Implementation Examples

The following JavaScript implementations demonstrate both DP styles for classic interview questions featured in the handbook.

### Top-Down Memoization: Climbing Stairs

```javascript
// LeetCode 70: Climbing Stairs
// dp(i) = number of ways to reach step i
// recurrence: dp(i) = dp(i-1) + dp(i-2)

function climbStairs(n) {
  const memo = new Map();               // cache for memoization

  function dfs(i) {
    if (i <= 2) return i;              // base cases: 1 or 2 ways
    if (memo.has(i)) return memo.get(i);
    const ways = dfs(i - 1) + dfs(i - 2);
    memo.set(i, ways);
    return ways;
  }

  return dfs(n);
}

```

This matches the recurrence discussed in the handbook's *Essential questions* list for Climbing Stairs.

### Bottom-Up with Space Optimization: Climbing Stairs

```javascript
function climbStairsIter(n) {
  if (n <= 2) return n;
  let prev = 1, cur = 2;               // dp(i-2), dp(i-1)

  for (let i = 3; i <= n; i++) {
    const next = prev + cur;           // dp(i) = dp(i-1) + dp(i-2)
    prev = cur;
    cur = next;
  }
  return cur;
}

```

This demonstrates the space-compression tip from the handbook: storing only the last two values reduces space from `O(n)` to `O(1)`.

### Bottom-Up Tabulation: 0/1 Knapsack

```javascript
/**
 * nums   – weights/value pairs [{w, v}, ...]
 * capacity – maximum weight the knapsack can hold
 * returns maximum total value
 */
function knapsack(nums, capacity) {
  const dp = new Array(capacity + 1).fill(0); // dp[w] = best value for weight w

  for (const { w, v } of nums) {
    // iterate backwards to avoid reusing the same item
    for (let cur = capacity; cur >= w; cur--) {
      dp[cur] = Math.max(dp[cur], dp[cur - w] + v);
    }
  }
  return dp[capacity];
}

```

This implementation appears in the handbook's "Recommended practice questions" section for 0/1 Knapsack problems.

## Key Resources in the Repository

The Tech Interview Handbook organizes DP content across several files:

- **[`apps/website/contents/algorithms/dynamic-programming.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/dynamic-programming.md)**: Core cheat-sheet containing the 9-step workflow, essential questions, and space optimization tips.

- **[`apps/website/contents/algorithms/array.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/array.md)**: General array techniques that often pair with DP, including sub-array and prefix sum patterns.

- **[`apps/website/contents/algorithms/string.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/string.md)**: DP applications for string subsequence problems like longest palindromic subsequence.

- **[`apps/website/contents/algorithms/matrix.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/matrix.md)**: DP on 2-D grids covering unique paths and minimum path sum variants.

- **[`apps/website/_courses/AlgorithmCourses.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/_courses/AlgorithmCourses.md)**: Curated DP-focused course recommendations referenced in the main cheat-sheet.

## Summary

- **Identify** DP problems by looking for optimization requests (max/min, count ways) and keywords like subsequence, grid, or knapsack.
- **Define** minimal state variables that uniquely describe sub-problems and formulate a correct recurrence relation before coding.
- **Implement** using either top-down memoization (recursive with cache) or bottom-up tabulation (iterative table filling).
- **Initialize** base cases properly to seed your computation with trivial sub-problem solutions.
- **Optimize** space by replacing full tables with rolling arrays when only recent states are needed, reducing complexity from `O(n)` to `O(1)` or `O(k)`.
- **Communicate** your state definition and recurrence clearly before writing code to demonstrate structured problem-solving.

## Frequently Asked Questions

### How do I know if a problem requires dynamic programming?

A problem likely requires dynamic programming if it asks for an optimal solution (maximum, minimum, or counting ways) and exhibits **optimal substructure** (optimal solution contains optimal sub-solutions) and **overlapping sub-problems** (same sub-problems solved multiple times). Signal phrases include "subsequence," "subarray," "grid paths," or "partition." According to the handbook, checking against essential questions like Climbing Stairs or Coin Change helps confirm the pattern.

### Should I use top-down or bottom-up DP in interviews?

Choose **top-down** when the recursive structure matches the problem definition naturally and you need to explore only a subset of states. Use **bottom-up** when you need to avoid recursion depth limits or when the problem requires computing all states anyway. The handbook notes that bottom-up often enables easier space optimization by storing only recent values.

### How do I optimize space in dynamic programming solutions?

Analyze your recurrence relation to determine how many previous states you need. If you only need the last `k` values (often `k=2` for Fibonacci-style problems), replace the full DP array with a **rolling array** or scalar variables. For example, in [`apps/website/contents/algorithms/dynamic-programming.md`](https://github.com/yangshun/tech-interview-handbook/blob/main/apps/website/contents/algorithms/dynamic-programming.md), the handbook explicitly recommends storing only the last two values when sufficient, reducing space complexity from `O(n)` to `O(1)`.

### What are the most important dynamic programming patterns to memorize?

The handbook emphasizes mastering **Climbing Stairs** (foundational state transition), **Coin Change** (unbounded knapsack variant), **House Robber** (decision at each step), and **0/1 Knapsack** (capacity-constrained optimization). These patterns generalize to most interview DP problems involving sequences, strings, and grids.