Dynamic Programming Coding Problems: 195 Questions with Solutions

195 dynamic programming coding problems — 10 easy · 110 medium · 75 hard — with solutions in 13 languages. Plus a step-by-step walkthrough and a 8-day plan.

  • Problems: 195
  • By difficulty: 10 easy · 110 medium · 75 hard
  • Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
  • Cost: Free on every plan; sign in to run and submit

Dynamic programming solves a problem by solving its smaller versions once each and remembering the answers. The problems here run from the one-dimensional cases (climbing stairs, house robber, the best subarray) to two-dimensional tables over strings and grids, and the skill is the same each time: name the state, write the recurrence, decide the order that makes every dependency ready before it is needed, then shrink the table to what the recurrence actually reads.

How dynamic programming works, step by step

numsdp207192331427111112best = 12 (houses 0, 2, 4)
Most money from non-adjacent houses, with dynamic programming. Example: nums = [2, 7, 9, 3, 1]
  1. No two neighbouring houses can both be robbed. Let dp[i] be the most money from houses 0..i: either skip house i and keep dp[i−1], or rob it and add nums[i] to dp[i−2], the best that leaves house i−1 alone.
  2. dp[0] = 2: with a single house, rob it. This is the base case every later cell builds on.
  3. dp[1] = max(dp[0], nums[1]) = max(2, 7) = 7: houses 0 and 1 are neighbours, so take the richer one, house 1.
  4. dp[2] = max(skip: 7, rob: 2 + 9 = 11) = 11. Robbing house 2 wins, so the best plan so far ends with house 2.
  5. dp[3] = max(skip: 11, rob: 7 + 3 = 10) = 11. Skipping wins: house 3 is worth less than what robbing it would give up.
  6. dp[4] = max(skip: 11, rob: 11 + 1 = 12) = 12. Robbing house 4 wins, so the best plan so far ends with house 4.
  7. The answer is dp[4] = 12. Walking back, a house was robbed wherever dp changes from its left neighbour: houses 0, 2 and 4, 2 + 9 + 1 = 12. One pass, O(n) time, and O(1) space keeping only the last two cells.

Dynamic Programming study plan

14 of the 195 Dynamic Programming problems (4 easy, 7 medium and 3 hard) over 8 days, about 8 h 10 min in all — the pattern first, then easiest to hardest. After that, the other 181 in the full list below are practice at your own pace. Then move on to Memoization.

Day 1

Learn the pattern: read the essentials and step through the walkthrough above, then solve these 3.

Day 2

Medium problems: the same pattern with one twist each. Name the twist before you code.

Day 3

More mediums. Before coding each one, write down what state the pattern keeps and when it changes.

Day 4

More mediums. Before coding each one, write down what state the pattern keeps and when it changes.

Day 5

More mediums. Before coding each one, write down what state the pattern keeps and when it changes.

Day 6

Hard problems: the pattern combined with a second idea. Give each a full attempt before reading the editorial.

Day 7

Another hard one. If it beats you after a real attempt, read the editorial, then solve it again tomorrow from memory.

Day 8

Another hard one. If it beats you after a real attempt, read the editorial, then solve it again tomorrow from memory.

Next topic: Memoization

Dynamic Programming: the essentials

When to reach for it

The question asks for a count of ways, a minimum or maximum cost, or whether something is achievable — and a choice made now changes what is possible later. If a brute-force recursion would solve the same subproblem many times (the same index, the same remaining amount, the same pair of prefixes), the subproblems overlap and DP applies. "Return every way" is different: listing answers is Backtracking.

The pattern

Write the recursion first, over a small state: f(i) for the best answer on the first i items, f(i, j) for two prefixes, f(a) for a remaining amount. Base cases are the states you can answer without recursing. Then memoise it (top-down) or fill a table in an order where every dependency is computed before it is read (bottom-up).

def coin_change(coins, amount):
    INF = amount + 1
    dp = [0] + [INF] * amount       # dp[a] = fewest coins making a
    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] <= amount else -1

Cost

States × work per state for time, and the number of states for space — often cut to one or two rows, because a row reads only the one before it. Coin change above is O(amount × coins) time and O(amount) space.

Common mistakes

  • A state that leaves out something the future depends on, such as whether you hold a stock or how many transactions remain.
  • Filling cells in an order that reads one not yet computed.
  • In counting problems, swapping the loops: coins outside counts combinations, amounts outside counts ordered sequences.
  • Using 0 to mean "impossible" in a minimisation, or recursing without a memo and paying exponential time.

Start with

All dynamic programming problems

Easy (10)

Medium (110)

Hard (75)

Companies that ask dynamic programming problems

  • Amazon 166 problems on dynamic programming
  • Google 155 problems on dynamic programming
  • Microsoft 47 problems on dynamic programming
  • Meta 32 problems on dynamic programming
  • Adobe 29 problems on dynamic programming
  • Uber 19 problems on dynamic programming
  • Bloomberg 10 problems on dynamic programming
  • Flipkart 7 problems on dynamic programming
  • Apple 3 problems on dynamic programming
  • Goldman Sachs 3 problems on dynamic programming
  • Zoho 3 problems on dynamic programming
  • TCS 2 problems on dynamic programming

Next topic: Memoization