Skip to content
advancedPhase 6 · Dynamic Programming

Interval DP

Solve problems on intervals like matrix chain multiplication and palindromes.

1h 15m
4 problems
Topic Progress0%

Interval DP Fundamentals

Interval DP solves problems on subarrays/substrings by considering all possible split points within an interval.

General Pattern

// dp[i][j] = optimal value for interval [i, j]
// Base case: dp[i][i] = 0 or some initial value
// Transition: Try all split points k in [i, j]

for (int len = 2; len <= n; len++) {        // interval length
    for (int i = 0; i <= n - len; i++) {     // start index
        int j = i + len - 1;                 // end index
        for (int k = i; k < j; k++) {        // split point
            dp[i][j] = optimize(dp[i][j], dp[i][k] + dp[k+1][j] + cost(i,k,j));
        }
    }
}

Matrix Chain Multiplication

Given matrices A1, A2, ..., An, find the minimum number of scalar multiplications needed to compute the product.

// p[] = dimensions, p[0] x p[1], p[1] x p[2], ..., p[n-1] x p[n]
// dp[i][j] = min cost to multiply matrices i to j
public int matrixChainOrder(int[] p) {
    int n = p.length - 1;  // number of matrices
    int[][] dp = new int[n][n];
    
    // Base case: cost to multiply single matrix = 0
    // dp[i][i] = 0 (already initialized)
    
    // Fill for chain lengths 2 to n
    for (int len = 2; len <= n; len++) {
        for (int i = 0; i <= n - len; i++) {
            int j = i + len - 1;
            dp[i][j] = Integer.MAX_VALUE;
            
            for (int k = i; k < j; k++) {
                // Cost = dp[i][k] + dp[k+1][j] + p[i]*p[k+1]*p[j+1]
                int cost = dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1];
                dp[i][j] = Math.min(dp[i][j], cost);
            }
        }
    }
    
    return dp[0][n - 1];
}

Trace Example

p = [10, 30, 5, 60] → 3 matrices: 10x30, 30x5, 5x60

len=2: dp[0][1] = 10*30*5 = 1500
       dp[1][2] = 30*5*60 = 9000

len=3: dp[0][2] = min(
         dp[0][0] + dp[1][2] + 10*5*60 = 0 + 9000 + 3000 = 12000,
         dp[0][1] + dp[2][2] + 10*30*60 = 1500 + 0 + 18000 = 19500
       ) = 12000

Answer: 12000 (multiply as (A1 x A2) x A3)

Minimum Score Triangulation

// Minimum score triangulation of polygon
public int minScoreTriangulation(int[] values) {
    int n = values.length;
    int[][] dp = new int[n][n];
    
    for (int len = 2; len < n; len++) {
        for (int i = 0; i < n - len; i++) {
            int j = i + len;
            dp[i][j] = Integer.MAX_VALUE;
            
            for (int k = i + 1; k < j; k++) {
                int cost = dp[i][k] + dp[k][j] + values[i] * values[k] * values[j];
                dp[i][j] = Math.min(dp[i][j], cost);
            }
        }
    }
    
    return dp[0][n - 1];
}

Key Insights for Interval DP

  1. Order of computation: Length 2 first, then length 3, etc.
  2. Split point: Try all possible k to find optimal split
  3. Cost function: Depends on the specific problem
  4. Base case: Single element intervals have 0 cost

Palindrome Problems with Interval DP

Palindrome Partitioning II

Minimum cuts needed to partition a string such that every substring is a palindrome.

// dp[i] = minimum cuts for s[0..i]
public int minCut(String s) {
    int n = s.length();
    boolean[][] isPalin = new boolean[n][n];
    int[] dp = new int[n];
    
    // Precompute palindrome table
    for (int len = 1; len <= n; len++) {
        for (int i = 0; i <= n - len; i++) {
            int j = i + len - 1;
            if (s.charAt(i) == s.charAt(j)) {
                if (len <= 3 || isPalin[i + 1][j - 1]) {
                    isPalin[i][j] = true;
                }
            }
        }
    }
    
    // Compute minimum cuts
    for (int i = 0; i < n; i++) {
        if (isPalin[0][i]) {
            dp[i] = 0;  // No cut needed if whole prefix is palindrome
        } else {
            dp[i] = i;  // Maximum cuts (cut at every position)
            for (int j = 0; j < i; j++) {
                if (isPalin[j + 1][i]) {
                    dp[i] = Math.min(dp[i], dp[j] + 1);
                }
            }
        }
    }
    
    return dp[n - 1];
}

Longest Palindromic Substring

// dp[i][j] = true if s[i..j] is palindrome
public String longestPalindrome(String s) {
    int n = s.length();
    boolean[][] dp = new boolean[n][n];
    int start = 0, maxLen = 1;
    
    // Base case: single character
    for (int i = 0; i < n; i++) dp[i][i] = true;
    
    // Check for length 2
    for (int i = 0; i < n - 1; i++) {
        if (s.charAt(i) == s.charAt(i + 1)) {
            dp[i][i + 1] = true;
            start = i;
            maxLen = 2;
        }
    }
    
    // Check for length 3 and above
    for (int len = 3; len <= n; len++) {
        for (int i = 0; i <= n - len; i++) {
            int j = i + len - 1;
            if (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]) {
                dp[i][j] = true;
                if (len > maxLen) {
                    start = i;
                    maxLen = len;
                }
            }
        }
    }
    
    return s.substring(start, start + maxLen);
}

Burst Balloons

// Maximum coins from bursting balloons
// Coins = nums[left] * nums[i] * nums[right] for burst balloon i
public int maxCoins(int[] nums) {
    int n = nums.length;
    int[] newNums = new int[n + 2];
    newNums[0] = 1;
    newNums[n + 1] = 1;
    for (int i = 0; i < n; i++) newNums[i + 1] = nums[i];
    
    int[][] dp = new int[n + 2][n + 2];
    
    // Fill for all interval lengths
    for (int len = 1; len <= n; len++) {
        for (int left = 1; left <= n - len + 1; left++) {
            int right = left + len - 1;
            
            for (int k = left; k <= right; k++) {
                int coins = newNums[left - 1] * newNums[k] * newNums[right + 1]
                           + dp[left][k - 1] + dp[k + 1][right];
                dp[left][right] = Math.max(dp[left][right], coins);
            }
        }
    }
    
    return dp[1][n];
}

Interval DP Pattern Summary

Problem dp[i][j] Transition
Matrix Chain Min cost for matrices i..j min(dp[i][k] + dp[k+1][j] + cost)
Burst Balloons Max coins for balloons i..j max(dp[left][k-1] + dp[k+1][right] + cost)
Palindrome Partition Min cuts for s[0..i] min(dp[j] + 1) if s[j+1..i] is palindrome
Longest Palindrome Is s[i..j] palindrome? s[i]==s[j] && dp[i+1][j-1]

Practice Problems

0/1solved
Burst Balloons
Interval DP

You are given n balloons, indexed from 0 to n - 1. Each balloon has a number on it represented by an array nums. You are asked to burst all the balloons. If you burst the ith balloon, you will get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 goes out of bounds of the array, then treat it as if there is a balloon with a 1 on it. Return the maximum coins you can collect by bursting the balloons wisely.

Example:

Input: nums = [3,1,5,8]

Output: 167

One optimal order: burst 1 (3*1*5=15), then 5 (3*5*8=120), then 8 (3*8*1=24), then 3 (1*3*1=3). Total = 15+120+24+3 = 167. Actually 167 comes from: burst 1→5→3→8 = 15+15+45+120=195? Let me recalculate. Optimal: burst 1 (15), then 5 (3*5*8=120), then 8 (3*8*1=24), then 3 (1*3*1=3) = 162? Actually the answer is 167 from bursting in order: 1,5,3,8.

Optimal Solution — O(n^3) time, O(n^2) space

Interval DP. Think of bursting the last balloon k in interval [left, right]. Then dp[left][right] = max over all k of (dp[left][k-1] + dp[k+1][right] + nums[left-1]*nums[k]*nums[right+1]).

class Solution {
    public int maxCoins(int[] nums) {
        int n = nums.length;
        int[] newNums = new int[n + 2];
        newNums[0] = 1;
        newNums[n + 1] = 1;
        for (int i = 0; i < n; i++) newNums[i + 1] = nums[i];
        
        int[][] dp = new int[n + 2][n + 2];
        
        for (int len = 1; len <= n; len++) {
            for (int left = 1; left <= n - len + 1; left++) {
                int right = left + len - 1;
                
                for (int k = left; k <= right; k++) {
                    int coins = newNums[left - 1] * newNums[k] * newNums[right + 1]
                               + dp[left][k - 1] + dp[k + 1][right];
                    dp[left][right] = Math.max(dp[left][right], coins);
                }
            }
        }
        
        return dp[1][n];
    }
}

Edge Cases:

  • Single balloon: return its value
  • Two balloons: burst in any order
  • All zeros: return 0
  • All ones: minimal coins

Quiz

1. In Interval DP, what is the order of computation?

Question 1 options

2. What is the time complexity of Interval DP problems?

Question 2 options

3. What is the primary purpose of Interval Dynamic Programming?

Question 3 options

4. What is a common mistake when implementing Interval Dynamic Programming?

Question 4 options

Flashcards

Question

What is the general pattern for Interval DP?

Answer

Process intervals by increasing length. For each interval [i,j], try all split points k. dp[i][j] = optimize(dp[i][k] + dp[k+1][j] + cost(i,k,j)).

Question

How does Burst Balloons differ from Matrix Chain Multiplication?

Answer

In Burst Balloons, the split point k is the LAST balloon burst, and cost depends on neighbors (left-1, k, right+1). In Matrix Chain, cost depends on dimensions at split.

Question

What is Interval Dynamic Programming?

Answer

Interval Dynamic Programming is a key concept in software engineering.

Question

When to use Interval Dynamic Programming?

Answer

Use Interval Dynamic Programming when building production systems that require reliability, scalability, and maintainability.

Question

Interval Dynamic Programming best practices

Answer

Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.

Revision Notes

Key Takeaways

  • 1.Interval DP: O(n^3) by trying all split points in each interval
  • 2.Process intervals by increasing length
  • 3.dp[i][j] represents optimal value for interval [i, j]
  • 4.Cost function depends on the split point and problem specifics

Interview Tips

  • Draw out small examples to understand interval structure
  • Clarify if you're bursting last or first at split point
  • Explain the order of computation (length 2, 3, ...)
  • Discuss how to reconstruct the actual solution

Cheat Sheet

Interval DP Cheat Sheet

General Pattern:

for (int len = 2; len <= n; len++) {
    for (int i = 0; i <= n - len; i++) {
        int j = i + len - 1;
        for (int k = i; k < j; k++) {
            dp[i][j] = optimize(dp[i][j], dp[i][k] + dp[k+1][j] + cost);
        }
    }
}

Key Problems:

  • Matrix Chain: min cost, cost = p[i]*p[k+1]*p[j+1]
  • Burst Balloons: max coins, cost = nums[left-1]*nums[k]*nums[right+1]
  • Palindrome Partition: min cuts, check if substring is palindrome

Time Complexity: O(n^3) - O(n^2) intervals × O(n) split points

Space Complexity: O(n^2) for dp table

Important: Process intervals by increasing length to ensure subintervals are solved first.