Pattern #67

1D Dynamic Programming

Master single-dimensional DP arrays and rolling variable space optimization. Express subproblems with one variable, identify transition windows, and optimize memory to O(1).

Must Solve

20 core questions — solve these first.

  1. 1.Climbing Stairs
    easy
  2. 2.Min Cost Climbing Stairs
    easy
  3. 3.House Robber
    medium
  4. 4.House Robber II
    medium
  5. 5.Fibonacci Number
    easy
  6. 6.Decode Ways
    medium
  7. 7.Coin Change
    medium
  8. 8.Coin Change II
    medium
  9. 9.Perfect Squares
    medium
  10. 10.Word Break
    medium
  11. 11.Maximum Subarray
    easy
  12. 12.Maximum Product Subarray
    medium
  13. 13.Longest Increasing Subsequence
    medium
  14. 14.Partition Equal Subset Sum
    medium
  15. 15.Target Sum
    medium
  16. 16.0/1 Knapsack — Space Optimized
    medium
  17. 17.Combination Sum IV
    medium
  18. 18.Delete and Earn
    medium
  19. 19.Integer Break
    medium
  20. 20.Best Time to Buy and Sell Stock variants
    medium

Also Important

10 essential 1D DP variations worth practicing.

  1. 21.Jump Game variants
    medium
  2. 22.Tribonacci Number
    easy
  3. 23.Domino and Tromino Tiling
    medium
  4. 24.House Robber style scheduling
    medium
  5. 25.Minimum Cost for Tickets
    medium
  6. 26.Number of Dice Rolls With Target Sum
    medium
  7. 27.Ugly Number II
    medium
  8. 28.Longest Valid Parentheses — DP approach
    hard
  9. 29.Maximum Sum Circular Subarray — related
    medium
  10. 30.Weighted Interval Scheduling — DP + Binary Search
    hard

How to Think

Define what one DP cell dp[i] represents, then build transitions from earlier positions or amounts.

  1. Answer mainly depends on position i?dp[i]
  2. Current answer depends on earlier positions?1D DP
  3. Only previous 1–2 states needed?Space Optimization O(1)
  4. State dimension is numerical (amount / sum)?1D Amount DP
  5. Need max subarray sum ending at i?Kadane 1D DP

Go Quick Reference — 1D DP

Compilable Go implementations showing Space-Optimized House Robber O(1) and 1D Coin Change Minimum Amount array.

package main

import "fmt"

// Space-Optimized 1D DP for House Robber: O(N) time, O(1) space
func rob(nums []int) int {
    if len(nums) == 0 {
        return 0
    }
    prev2, prev1 := 0, 0
    for _, num := range nums {
        // Transition: current = max(skip, take)
        take := num + prev2
        skip := prev1
        current := take
        if skip > take {
            current = skip
        }
        prev2 = prev1
        prev1 = current
    }
    return prev1
}

// 1D Amount DP for Coin Change: O(Amount * Coins) time, O(Amount) space
func coinChange(coins []int, amount int) int {
    dp := make([]int, amount+1)
    const inf = 1e9
    for i := 1; i <= amount; i++ {
        dp[i] = inf
    }
    dp[0] = 0 // Base case

    for a := 1; a <= amount; a++ {
        for _, coin := range coins {
            if a >= coin && dp[a-coin]+1 < dp[a] {
                dp[a] = dp[a-coin] + 1
            }
        }
    }
    if dp[amount] == inf {
        return -1
    }
    return dp[amount]
}

func main() {
    fmt.Println("Max Robbed:", rob([]int{2, 7, 9, 3, 1}))       // 12
    fmt.Println("Min Coins:", coinChange([]int{1, 2, 5}, 11)) // 3
}

👉 1D DP: O(N) or O(Amount) time and O(1) or O(N) space.

Core 1D DP Patterns & Shapes

Common 1D Transition Shapes

• 1 State Back: dp[i] ← dp[i-1] (Kadane, Stock buy/sell).
• 2 States Back: dp[i] ← dp[i-1], dp[i-2] (Climbing Stairs, House Robber).
• All Previous j < i: dp[i] ← max(dp[j]) (LIS - O(N²) time).
• Amount / Capacity Shift: dp[a] ← dp[a - coin] (Coin Change, Knapsack).

"Ending At" vs "Overall Best"

• In LIS and Kadane, dp[i] means "best answer ending EXACTLY at index i".
• The final answer is max(dp) across the array, NOT necessarily dp[N-1]!
• Always distinguish between target cell vs overall array maximum.

Visual Memory Rule
Define dp[i] Cell Meaning → Set Base Cases → Transition → Answer
Previous 1–2 States → Rolling variables optimize space to O(1)
0/1 Knapsack 1D Table → Capacity loop runs Right-to-Left
Unbounded Knapsack 1D Table → Capacity loop runs Left-to-Right
LIS / Subarray DP → Answer is max(dp), not always dp[last]

1D DP Variants & Space Optimization

0/1 vs Unbounded 1D Update Direction

• 0/1 Knapsack / Subset Sum: Update capacity Right to Left (w = W down to weight) to prevent item reuse.
• Unbounded Knapsack / Coin Change: Update capacity Left to Right (w = weight up to W) to allow item reuse.

Rolling Variables Technique

When dp[i] depends only on a fixed sliding window of size K (e.g. 2 states back):
Replace the full dp[N] array with K variables (prev2, prev1, current).
Reduces extra space from O(N) to O(1).

1D State Does Not Always Mean Array Index

The single state dimension in 1D DP can represent:
• Array Index: dp[i] (House Robber, LIS).
• Numerical Amount / Capacity: dp[amount] or dp[weight] (Coin Change, Knapsack).
• Sum / Count: dp[target] (Target Sum).
As long as one variable uniquely identifies the subproblem, it is a 1D DP pattern.

Common Interview Mistakes

  • • Coding before explicitly defining what dp[i] represents in plain language.
  • • Wrong base case initializations (e.g. using 0 for minimum problems instead of INF).
  • • Returning dp[N-1] when the answer is max(dp) across the array (common mistake in LIS and Kadane).
  • • Running 0/1 Knapsack 1D capacity loop left-to-right (accidentally allowing item reuse).
  • • Assuming all 1D DP solutions run in O(N) time (LIS is O(N²) because each state scans all j < i).
  • • Optimizing space to O(1) prematurely before validating the full array transition logic.
  • • Confusing array index state (dp[i]) with numerical amount state (dp[amount]).
  • • Failing to handle negative numbers in Maximum Product Subarray (requires currentMax and currentMin).

Interview Rules

Single parameter defines subproblem → 1D DP
Rule 1                              → Define dp[i] meaning explicitly
Rule 2                              → Set base cases
Rule 3                              → Identify previous state window (1 state, 2 states, or all j < i)
Rule 4                              → 0/1 Knapsack 1D = Capacity loop Right-to-Left
Rule 5                              → Unbounded Knapsack 1D = Capacity loop Left-to-Right
Rule 6                              → Window of size 1–2? → Rolling variables for O(1) space
Time Complexity                     → States × Work per State
Space Complexity                    → O(N) Array or O(1) Rolling Variables

💡 Golden Rule: If one variable completely describes the subproblem, store the answer in one DP dimension and build each state from already-solved states.

Production Thinking

Budget & Financial Optimization → 1D amount DP allocates cloud resources or spending budgets under fixed limits.

Time Window Scheduling → dp[t] tracks optimal system throughput or job completions by time t.

Resource Capacity Management → 1D capacity tables model memory, storage, or weight thresholds with O(1) memory overhead.

Production warning → space optimization reduces array size, but premature variable overwrites produce subtle bug corruptions.

Remember This

1D DP State: dp[i] or dp[amount]
Golden Steps: Define Cell → Base Cases → Transition → Fill → Answer
0/1 Knapsack 1D: Loop capacity Right-to-Left
Unbounded 1D: Loop capacity Left-to-Right
LIS & Kadane: dp[i] means "ending at i"; final answer is max(dp)
Rolling variables (prev2, prev1) achieve O(1) memory