Hello! Let's dive into our next lesson on Dynamic Programming.
In the last session, we mastered the Longest Increasing Subsequence (LIS) problem, exploring both a standard O(n²) DP solution and a clever O(n log n) optimization. You saw how DP can be applied to find optimal subsequences.
Today, we're tackling a different but equally important category of DP problems with the Matrix Chain Multiplication (MCM) problem. This is a classic problem that introduces a powerful pattern known as Partition DP or Interval DP. Your learning outcome is to solve the Matrix Chain Multiplication problem using dynamic programming. Mastering this pattern is crucial for interviews, as it provides a framework for solving any problem that involves optimally splitting a sequence or an interval.
1. Understanding the Problem
Imagine you have a chain of matrices to multiply, say A * B * C * D. Matrix multiplication is associative, meaning you can group the multiplications in any way you like, e.g., ((A*B)*C)*D or (A*(B*C))*D. While the final result matrix will be the same, the total number of scalar multiplications (the computational cost) can vary dramatically depending on the parenthesization. Our goal is to find the ordering that minimizes this total cost.
The Cost of Multiplication
First, let's recall how matrices are multiplied. To multiply a matrix M1 of dimensions p x q and a matrix M2 of dimensions q x r, the number of scalar multiplications required is p * q * r. The resulting matrix will have dimensions p x r.
The video below explains this rule and provides a clear example showing why the order of multiplication matters.
DP 48. Matrix Chain Multiplication | MCM | Partition DP Starts 🔥
Let's watch this segment from the 'take U forward' YouTube channel. It perfectly illustrates the core problem: how different ways of parenthesizing the same matrix chain lead to vastly different computational costs.
Watch from 04:30 to 12:29. Focus on: The rule for matrix multiplication compatibility and cost calculation. The concrete example with matrices A, B, and C, which shows a cost of 4500 operations for one grouping versus 27000 for another.
Problem Formulation
In a typical problem setup, you aren't given the matrices themselves, but an array of their dimensions. For N-1 matrices, you will be given an array arr of size N. The dimensions of the i-th matrix (1-indexed) are given by arr[i-1] x arr[i].
For example, if arr = [10, 20, 30, 40], we have N=4, which represents N-1=3 matrices:
M1: 10 x 20 (arr[0] x arr[1])M2: 20 x 30 (arr[1] x arr[2])M3: 30 x 40 (arr[2] x arr[3])
Our task is to find the minimum number of scalar multiplications to compute M1 * M2 * M3.
2. Devising a Strategy: Partition DP
The MCM problem fits a pattern called Partition DP. The general idea is to take a problem on a range [i, j] and try every possible way to split it into two subproblems.
The strategy is:
- Start with the entire block/range. For our problem, this is the full chain of matrices, say from matrix
ito matrixj. - Try all partitions. We can place the last multiplication at any point
kbetweeniandj. This splits the problem into two independent subproblems: multiplying matrices(i...k)and multiplying matrices(k+1...j). - Return the best possible result. We calculate the cost for each split point
kand take the minimum. The total cost for a split atkis:(cost to solve subproblem 1) + (cost to solve subproblem 2) + (cost to multiply their results).
Let's watch a video that outlines this generic approach and begins to formalize it for MCM.
DP 48. Matrix Chain Multiplication | MCM | Partition DP Starts 🔥
This video segment develops the recursive structure for Partition DP. It introduces the function f(i, j) and the loop for trying all partition points k.
Watch from 15:04 to 19:46. Pay attention to the three general rules outlined for solving partition-style problems. This is a mental model you can reuse for many other problems.
3. From Recursion to Memoization (Top-Down DP)
Let's formalize the recursive solution. We can define a function solve(i, j) that returns the minimum cost to multiply matrices from index i to j.
-
Base Case: If
i >= j, we have one or zero matrices. The cost is 0. -
Recursive Step: We iterate a partition point
kfromitoj-1. For eachk, we split the chain into(i...k)and(k+1...j). The cost for this partition is:solve(i, k) + solve(k+1, j) + cost_to_multiply_resultsThe cost to multiply the two resulting matrices is
arr[i-1] * arr[k] * arr[j]. (The result of(i...k)is a matrix of sizearr[i-1] x arr[k], and the result of(k+1...j)is a matrix of sizearr[k] x arr[j]).
This plain recursive solution is extremely slow (exponential time) because it recalculates the same subproblems (solve(i,j) for the same i and j) repeatedly. We can optimize this using memoization.
We'll use a 2D array, dp[i][j], to store the result of solve(i, j). Before computing, we check if dp[i][j] already has a stored value. If so, we return it; otherwise, we compute, store, and then return.
The following resource provides a clear, commented Java implementation of this memoized approach.
Let's look at the 'Matrix Chain Multiplication' article from GeeksforGeeks. It provides a clean Java implementation of the memoized solution we just discussed.
Read the section named '[Better Approach 1 ] Using Top-Down DP (Memoization)'. Focus on the Java code. Notice how the recursive structure is preserved, but a memo[][] table is used to store and retrieve results, avoiding redundant computations.
The memoized solution has:
- Time Complexity:
O(N³)- There areO(N²)states(i, j). For each state, we run a loop forkthat takesO(N)time. - Space Complexity:
O(N²)for the DP table, plusO(N)for the recursion stack depth.
4. The Tabulation Approach (Bottom-Up DP)
For interview settings and competitive programming, it's often best to use the iterative tabulation method. It avoids recursion overhead and makes the space complexity more explicit.
The idea is to solve for smaller chains first and use those results to build solutions for larger chains.
- Initialize a
dp[N][N]table. - The cost of multiplying a single matrix is 0, so
dp[i][i] = 0for alli. This is our base case. - We iterate over the length of the chain,
len, from 2 up toN-1. - For each length, we iterate through all possible start indices
i. The end indexjis theni + len - 1. - Inside this loop, we apply the same recurrence as before: iterate a partition point
kfromitoj-1and find the minimum cost.
dp[i][j] = min(dp[i][k] + dp[k+1][j] + arr[i-1] * arr[k] * arr[j]) for k from i to j-1.
The following video brilliantly explains this conversion from the memoized solution to the tabulated one.
DP 49. Matrix Chain Multiplication | Bottom-Up | Tabulation
This follow-up video from 'take U forward' demonstrates how to convert the MCM solution to the bottom-up (tabulation) approach. This is a critical skill.
Watch the video, paying special attention to these parts: (00:49 - 02:13): Setting up the base case dp[i][i] = 0. (04:43 - 06:17): Understanding the order of loops. The outer loop for i runs from n-1 down to 1, and the inner loop for j runs from i+1 to n-1. This bottom-up filling of the DP table is key. (06:17 - 08:48): Seeing the final tabulated code and its complexity analysis.
The final answer will be in dp[1][N-1] (if using 1-based indexing for matrices) or dp[0][N-1] (if using 0-based array indexing for the arr of dimensions, which is more common in Java).
The image below, from the classic CLRS textbook, shows what the dp table (labeled m) looks like after being filled by the tabulation algorithm. The algorithm fills the table diagonally, moving away from the main diagonal, corresponding to solving for increasing chain lengths.

Test your understanding!
Given the dimension array arr = [2, 1, 3, 4], which represents three matrices: M1 (2x1), M2 (1x3), and M3 (3x4).
The problem is to find the minimum cost to multiply M1*M2*M3. This corresponds to solve(i=1, j=3) if we use 1-based matrix indexing.
What are the possible partition points k? Calculate the total cost for each partition.
-
Case 1: Partition at k=1. This means we compute
(M1) * (M2 * M3).- Cost of
solve(1, 1)= ? - Cost of
solve(2, 3)= ? (M2 * M3) - Cost of combining the results = ?
- Total cost = ?
- Cost of
-
Case 2: Partition at k=2. This means we compute
(M1 * M2) * (M3).- Cost of
solve(1, 2)= ? (M1 * M2) - Cost of
solve(3, 3)= ? - Cost of combining the results = ?
- Total cost = ?
- Cost of
What is the minimum cost?
Show answer
-
Case 1: Partition at k=1 (M1 * (M2*M3))
- Cost of
solve(1, 1)= 0 (base case). - Cost of
solve(2, 3)(M2 * M3) =arr[1]*arr[2]*arr[3]= 1 * 3 * 4 = 12. - Cost of combining results (a 2x1 matrix with a 1x4 matrix) =
arr[0]*arr[1]*arr[3]= 2 * 1 * 4 = 8. - Total cost = 0 + 12 + 8 = 20.
- Cost of
-
Case 2: Partition at k=2 ((M1*M2) * M3)
- Cost of
solve(1, 2)(M1 * M2) =arr[0]*arr[1]*arr[2]= 2 * 1 * 3 = 6. - Cost of
solve(3, 3)= 0 (base case). - Cost of combining results (a 2x3 matrix with a 3x4 matrix) =
arr[0]*arr[2]*arr[3]= 2 * 3 * 4 = 24. - Total cost = 6 + 0 + 24 = 30.
- Cost of
The minimum cost is 20.
Conclusion
You have successfully learned how to solve the Matrix Chain Multiplication problem, a cornerstone of dynamic programming. This lesson introduced you to the powerful Partition DP pattern, which you can apply to a variety of problems involving optimal splitting of intervals.
Key Takeaways:
- Problem: Find the minimum number of scalar multiplications to multiply a chain of matrices. The parenthesization matters.
- Pattern: This is a classic Partition DP problem. The core idea is to define a function
solve(i, j)and iterate through all possible split pointskwithin that range. - Recurrence Relation:
cost(i, j) = min_{i <= k < j} { cost(i, k) + cost(k+1, j) + cost_of_combining }. - Implementation: You can solve this with a top-down (memoized recursion) or bottom-up (tabulation) approach. Both have
O(N³)time andO(N²)space complexity. - Tabulation Strategy: The bottom-up approach iteratively solves for increasing chain lengths, which is a common and efficient way to handle interval-based DP problems.
Preview of the Next Lesson:
We've spent a lot of time on Dynamic Programming, a powerful technique for finding optimal solutions. In the next lesson, we will switch gears to another important algorithmic paradigm: Greedy Algorithms. We will explore problems like Activity Selection and Fractional Knapsack, learning when a greedy choice can lead to a global optimum, which is often faster and simpler than a full DP solution.