Skip to content
ΣDSA Patterns
Menu
Language

Pattern #22

One-Dimensional DP

Essential

Define dp[i] clearly, then relate it to smaller indices.

When to use

Optimal answer on a prefix, or ways/min cost to reach index i from earlier states only.

Recognition cues

  • Climbing stairs / house robber
  • Coin change / word break
  • LIS (patience or O(n²) DP)

Common pitfalls

  • Unclear state definition (what does dp[i] mean?)
  • Wrong iteration order for dependencies
  • Off-by-one on base cases

90-second recognition drill

Which pattern fits best?

  • Climbing stairs / house robber
  • Coin change / word break
  • LIS (patience or O(n²) DP)

Interactive

Mental model

A full worked walkthrough of the invariant. Pause, scrub the dots, or use ← →. Aim to narrate each step yourself.

Step 1 of 8
0
1
2
3
4
5
6

dp[0]=0, else inf

Fewest coins for amount 6 using coins {1,2,5}.

How to think about it

Name dp[i] in plain language (min coins for amount i; max money through house i). Express it using earlier cells. Fill in an order that respects dependencies. Compress space if only last few cells matter.

Template shapes

Shape Core move Notes
Linear dp[i] from dp[i-1], dp[i-2] Robber, stairs
Unbounded knapsack-ish Loop coins outer or inner Coin change
LIS style dp[i]=max over j<i O(n²) baseline

Complexity baseline

Typically O(n) or O(n·W); space O(n) or O(1) rolled.

From template to problem

  1. Write dp[i] meaning + base cases.
  2. Write the transition.
  3. Choose loop bounds carefully.
  4. Return dp[target] (or max over dp).

Template

Same skeleton in TypeScript, Python, and C#. Adapt the invariant; keep the structure.

One-Dimensional DP · Template
/** 1D DP template: Coin Change (fewest coins). dp[x] = min coins for amount x. */
export function coinChange(coins: number[], amount: number): number {
  const INF = amount + 1;
  const dp = new Array<number>(amount + 1).fill(INF);
  dp[0] = 0;
  for (let x = 1; x <= amount; x++) {
    for (const c of coins) {
      if (c <= x) dp[x] = Math.min(dp[x]!, dp[x - c]! + 1);
    }
  }
  return dp[amount]! >= INF ? -1 : dp[amount]!;
}
/** 1D DP template: Coin Change (fewest coins). dp[x] = min coins for amount x. */
export function coinChange(coins: number[], amount: number): number {
  const INF = amount + 1;
  const dp = new Array<number>(amount + 1).fill(INF);
  dp[0] = 0;
  for (let x = 1; x <= amount; x++) {
    for (const c of coins) {
      if (c <= x) dp[x] = Math.min(dp[x]!, dp[x - c]! + 1);
    }
  }
  return dp[amount]! >= INF ? -1 : dp[amount]!;
}
#StatusProblemTypeDone
  1. 1#70 Climbing StairsGuide
  2. 2#139 Word BreakGuide
  3. 3#198 House RobberGuide
  4. 4#213 House Robber IIGuide
  5. 5#300 Longest Increasing SubsequenceGuide
  6. 6#322 Coin ChangeGuide