Pattern #64

Dynamic Programming

Master overlapping subproblems and optimal substructure. Solve once, memoize results, transition between states, and optimize space from bottom-up tables.

Must Solve

25 core questions โ€” solve these first.

  1. 1.Climbing Stairs
    easy
  2. 2.House Robber
    medium
  3. 3.House Robber II
    medium
  4. 4.Coin Change
    medium
  5. 5.Coin Change II
    medium
  6. 6.Maximum Product Subarray
    medium
  7. 7.Longest Increasing Subsequence
    medium
  8. 8.Longest Common Subsequence
    medium
  9. 9.Word Break
    medium
  10. 10.Decode Ways
    medium
  11. 11.Unique Paths
    medium
  12. 12.Minimum Path Sum
    medium
  13. 13.Partition Equal Subset Sum
    medium
  14. 14.Target Sum
    medium
  15. 15.0/1 Knapsack
    medium
  16. 16.Edit Distance
    medium
  17. 17.Palindromic Substrings
    medium
  18. 18.Longest Palindromic Subsequence
    medium
  19. 19.Best Time to Buy and Sell Stock with Cooldown
    medium
  20. 20.Best Time to Buy and Sell Stock III
    hard
  21. 21.Dungeon Game
    hard
  22. 22.Interleaving String
    medium
  23. 23.Distinct Subsequences
    hard
  24. 24.Burst Balloons
    hard
  25. 25.House Robber III
    medium

Also Important

15 essential DP variations worth practicing.

  1. 26.Fibonacci Number
    easy
  2. 27.Min Cost Climbing Stairs
    easy
  3. 28.Combination Sum IV
    medium
  4. 29.Perfect Squares
    medium
  5. 30.Triangle
    medium
  6. 31.Maximal Square
    medium
  7. 32.Longest Palindromic Substring
    medium
  8. 33.Regular Expression Matching
    hard
  9. 34.Wildcard Matching
    hard
  10. 35.Minimum Falling Path Sum
    medium
  11. 36.Cherry Pickup
    hard
  12. 37.Stone Game
    medium
  13. 38.Delete and Earn
    medium
  14. 39.Integer Break
    medium
  15. 40.Maximum Length of Repeated Subarray
    medium

How to Think

Before writing DP code, answer the 4 questions: State definition, Cell Meaning, Transitions, and Base Cases.

  1. Same smaller problem repeating?Dynamic Programming
  2. Can I describe the problem with a state?dp[state] = answer
  3. Does current answer depend on previous states?Transition
  4. Recursive solution repeats work?Memoization (Top-Down)
  5. Can I compute states in dependency order?Tabulation (Bottom-Up)
  6. Take current item or skip current item?Take / Skip Pattern
  7. Two strings comparison or alignment?dp[i][j]
  8. Grid reachability or minimum cost path?dp[r][c]

Go Quick Reference โ€” Dynamic Programming

Compilable Go implementations showing Top-Down Memoization and Space-Optimized Bottom-Up Tabulation.

package main

import "fmt"

// Top-Down Memoization with int64 overflow protection
func coinChangeMemo(coins []int, amount int, memo map[int]int64) int64 {
    if amount == 0 {
        return 0
    }
    if amount < 0 {
        return -1
    }
    if val, exists := memo[amount]; exists {
        return val
    }

    var minCoins int64 = 1e18 // Use large int64 sentinel to prevent overflow
    for _, coin := range coins {
        res := coinChangeMemo(coins, amount-coin, memo)
        if res >= 0 && res+1 < minCoins {
            minCoins = res + 1
        }
    }

    if minCoins == 1e18 {
        memo[amount] = -1
    } else {
        memo[amount] = minCoins
    }
    return memo[amount]
}

// Bottom-Up Tabulation with Space Optimization O(1) space
func robTabulation(nums []int) int {
    if len(nums) == 0 {
        return 0
    }
    var prev2, prev1 int = 0, 0
    for _, num := range nums {
        // Core invariant: current best = max(skip current, rob current + best 2 houses back)
        take := num + prev2
        skip := prev1
        current := take
        if skip > take {
            current = skip
        }
        prev2 = prev1
        prev1 = current
    }
    return prev1
}

func main() {
    memo := make(map[int]int64)
    fmt.Println("Min Coins:", coinChangeMemo([]int{1, 2, 5}, 11, memo)) // 3
    fmt.Println("Max Robbed:", robTabulation([]int{2, 7, 9, 3, 1}))    // 12
}

๐Ÿ‘‰ Top-Down & Bottom-Up: O(N ร— Transitions) time and O(N) or O(1) space.

Core DP Patterns & Mechanics

The 4 Golden Questions

1. State: What parameters uniquely identify a subproblem?
2. Meaning: What exactly does dp[state] represent?
3. Transition: How is current state computed from smaller solved states?
4. Base Case: What are the known trivial boundaries?

Take / Skip Decision Framework

At item i, evaluate:
โ€ข Skip: Inherit answer from dp[i-1].
โ€ข Take: Combine item value with dp[i-1][rem_capacity] or dp[i-2].
Choose max() or min() depending on goal.

Visual Memory Rule
Repeated subproblems โ†’ Store & reuse state
Take / Skip decision โ†’ dp[i] = opt(dp[i-1], val + dp[i-2])
0/1 Knapsack 1D table โ†’ Iterate capacity right to left
Unbounded Knapsack 1D โ†’ Iterate capacity left to right
2D String Matching โ†’ dp[i][j] diagonal match or top/left max
Time Complexity โ†’ Number of States ร— Work per State

DP Families & Variants

1D & Grid DP

โ€ข 1D DP: State depends on single index dp[i] (Climbing Stairs, House Robber, LIS).
โ€ข Grid DP: State represents cell dp[r][c] moving down or right (Unique Paths, Min Path Sum).

2D String & Knapsack DP

โ€ข String DP: dp[i][j] compares prefix of string A with prefix of string B (LCS, Edit Distance).
โ€ข Knapsack: dp[w] tracks maximum value for capacity w (0/1 vs Unbounded).

0/1 vs Unbounded Knapsack Loop Direction

In 1D space-optimized Knapsack tables:
โ€ข 0/1 Knapsack (each item used once): Loop capacity right to left (w = W down to weight) to read unchanged values from previous item pass.
โ€ข Unbounded Knapsack (items reused freely): Loop capacity left to right (w = weight up to W) so newly updated values can be immediately reused.

Common Interview Mistakes

  • โ€ข Coding before clearly defining what dp[state] means in plain language.
  • โ€ข Leaving necessary constraint variables out of the state definition (e.g. remaining capacity, holding stock, or transaction count).
  • โ€ข Using the wrong loop direction in 1D Knapsack (updating left-to-right in 0/1 Knapsack accidentally reuses items multiple times).
  • โ€ข Incorrect base cases or failing to initialize unreachable states to infinity or negative infinity.
  • โ€ข Integer overflow when counting total combinations or paths (forgetting int64 guards or modulo arithmetic).
  • โ€ข Optimizing space to O(1) or O(N) prematurely before getting the full multi-dimensional DP table logic correct.
  • โ€ข Confusing continuous subarrays (contiguous elements) with non-continuous subsequences (can skip elements).

Interview Rules

Repeated Subproblems โ†’ Dynamic Programming
Step 1              โ†’ Define dp[state] meaning explicitly
Step 2              โ†’ Identify decision choices (Take vs Skip)
Step 3              โ†’ Formulate transition equation
Step 4              โ†’ Set boundary base cases
0/1 Knapsack 1D     โ†’ Right-to-Left capacity loop
Unbounded 1D        โ†’ Left-to-Right capacity loop
2D String Matching  โ†’ Matrix dp[i][j]
Time Complexity     โ†’ Total States ร— Work per State
Space Optimization  โ†’ Optimize array dimensions after correctness

๐Ÿ’ก Golden Rule: Define exactly what one DP state means, then express that state using smaller already-solved states.

Production Thinking

Resource & Pricing Optimization โ†’ matching cloud servers or inventory to budget constraints uses 0/1 or Unbounded Knapsack DP states.

Sequence Alignment & Diff Tools โ†’ git diffs, document comparison, and DNA sequence matching rely on LCS and Edit Distance 2D DP matrices.

Workflow & State Scheduling โ†’ state machine DP optimizes multi-stage system pipelines with cooling periods and transaction limits.

Production warning โ†’ DP table size scales with input values (pseudopolynomial time); huge capacities require continuous approximations, branch-and-bound, or greedy heuristics.

Remember This

Identify repeating subproblems
Define dp[state] cell meaning
Formulate state transition formula
Establish correct base cases
Top-Down (Memoization) or Bottom-Up (Tabulation)
Check loop direction for 1D Knapsack tables
Verify bounds and avoid integer overflow