Pattern #22
One-Dimensional DP
EssentialDefine 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
- Write dp[i] meaning + base cases.
- Write the transition.
- Choose loop bounds carefully.
- 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]!;
}
#StatusProblemTypeDifficultyDone
- 1#70 Climbing StairsGuideeasy
- 2#139 Word BreakGuidemedium
- 3#198 House RobberGuidemedium
- 4#213 House Robber IIGuidemedium
- 5#300 Longest Increasing SubsequenceGuidemedium
- 6#322 Coin ChangeGuidemedium