Definition
Row · column
Each C[i, j] is a dot product of row i of A with column j of B.
Standard matrix multiplication builds each result cell as a row × column dot product: C[i, j] = sum(A[i, k] * B[k, j]), only when inner dimensions match. This tutorial covers the rule, triple nested loops, a live preview, worked C# examples, edge cases, and complexity.
Row · column
Each C[i, j] is a dot product of row i of A with column j of B.
(m×n)(n×p)
AB exists only when columns of A equal rows of B; result is m×p.
i, j, k
Outer i/j pick a cell; inner k accumulates products.
Start at 0
Every result cell is a running sum — initialize before adding.
Show 3×3
Run the classic 3×3 sample product in the browser.
Not cell×cell
This is true matrix product — not element-wise multiply.
Matrix multiplication combines a row from A with a column from B. If A is m × n and B is n × p, then AB is defined and has size m × p, with C[i, j] = sum over k of A[i, k] * B[k, j].
This is not cell-by-cell multiplication (Hadamard product). Order matters: AB is generally not equal to BA.
It is a classic interview problem that tests 2D indexing, accumulation, and understanding of linear-algebra shape rules.
Each output entry is one row dotted with one column.
cols(A) must equal rows(B).
i and j pick the cell; k walks the shared dimension.
Square case uses cubic work with the basic algorithm.
In short: if shapes are compatible, zero-init C, then for each i, j accumulate A[i, k] * B[k, j] over k.
Given compatible matrices A and B, build product C = AB using row–column dot products.
// (m x n) * (n x p) -> (m x p)
// C[i, j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + ...
// Not the same as A[i, j] * B[i, j] | Item | Type | Description |
|---|---|---|
A, B | int[,] | Compatible matrices: cols(A) == rows(B). |
| Return / print | matrix / text | Product matrix of size rows(A) × cols(B). |
function multiply(A, B):
n <- size
C <- n x n matrix of zeros
for i from 0 to n - 1:
for j from 0 to n - 1:
for k from 0 to n - 1:
C[i, j] <- C[i, j] + A[i, k] * B[k, j]
return C | Method | Idea | Notes |
|---|---|---|
| Triple nested loops | Accumulate A[i, k]*B[k, j] | Interview default — clear and correct |
| Element-wise (Hadamard) | A[i, j] * B[i, j] | Different operation — same shape required |
| Library helper / BLAS | Library product | Production path; show loops in interviews |
| Goal | Pattern |
|---|---|
| Accumulate cell | result[i, j] += a[i, k] * b[k, j] |
| Triple loop | for i / for j / for k |
| Zero-init | new int[n][n] |
| Shape check | a.GetLength(1) == b.GetLength(0) (cols A == rows B) |
| Result size | m x p when A is m x n, B is n x p |
| Trace one cell | Top-left 3×3 sample: 1*9 + 2*6 + 3*3 = 30 |
Same word “multiply” — very different meanings.
sum A[i, k]*B[k, j]This page — classic interview style
A[i, j] * B[i, j]Element-wise — needs same shape
library mulFast in apps; show loops in interviews
state shape firstSay (m×n)(n×p)→m×p before coding
Reach for true matrix products when rows must combine with columns.
Triple loops plus shape rules are a common warm-up.
Natural step up from addition/division in this chain.
Compose maps, graphics, and simple ML layers.
Practice running sums over a shared index k.
Clarify when the interviewer wants cell-by-cell multiply.
Key benefit: one short problem that locks in indexing, accumulation, and the (m×n)(n×p)→m×p rule.
Uses the same 3×3 matrices as Example 1. Click to display both inputs and the product matrix.
Three complete C# programs — classic 3×3 product, easy-to-verify 2×2, and a shape-safe general multiplier. Click View Output to reveal sample console results.
Triple nested loops with a zero-initialized result matrix.
Classic interview-style implementation with helpers for multiply and display.
using System;
class Program
{
const int N = 3;
static int[,] MultiplyMatrices(int[,] a, int[,] b)
{
int[,] result = new int[N, N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
for (int k = 0; k < N; k++)
{
result[i, j] += a[i, k] * b[k, j];
}
}
}
return result;
}
static void DisplayMatrix(int[,] matrix)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
Console.Write(matrix[i, j]);
if (j + 1 < N)
{
Console.Write("\t");
}
}
Console.WriteLine();
}
}
static void Main()
{
int[,] firstMatrix = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
};
int[,] secondMatrix = {
{ 9, 8, 7 },
{ 6, 5, 4 },
{ 3, 2, 1 },
};
int[,] result = MultiplyMatrices(firstMatrix, secondMatrix);
Console.WriteLine("First Matrix:");
DisplayMatrix(firstMatrix);
Console.WriteLine("\nSecond Matrix:");
DisplayMatrix(secondMatrix);
Console.WriteLine("\nResult Matrix:");
DisplayMatrix(result);
}
} The innermost loop computes one dot product for each result cell: result[i, j] += a[i, k] * b[k, j]. Top-left output is 1*9 + 2*6 + 3*3 = 30.
Same logic on a smaller matrix so you can verify by hand.
Same triple-loop pattern with values that are easy to dry-run.
using System;
class Program
{
const int N = 2;
static int[,] MultiplyMatrices(int[,] a, int[,] b)
{
int[,] result = new int[N, N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
for (int k = 0; k < N; k++)
{
result[i, j] += a[i, k] * b[k, j];
}
}
}
return result;
}
static void PrintMatrix(string title, int[,] m)
{
Console.WriteLine(title);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
Console.Write(m[i, j] + " ");
}
Console.WriteLine();
}
}
static void Main()
{
int[,] a = { { 1, 2 }, { 3, 4 } };
int[,] b = { { 5, 6 }, { 7, 8 } };
int[,] r = MultiplyMatrices(a, b);
PrintMatrix("A", a);
Console.WriteLine();
PrintMatrix("B", b);
Console.WriteLine();
PrintMatrix("AB", r);
}
} Top-left value is 1*5 + 2*7 = 19; top-right is 1*6 + 2*8 = 22. Matching the printed AB confirms the accumulation logic.
Drop fixed N and enforce cols(A) == rows(B).
Checks inner dimensions, then multiplies any compatible m×n by n×p.
using System;
using System.Text;
class Program
{
static bool CanMultiply(int[,] a, int[,] b)
{
if (a == null || b == null || a.GetLength(0) == 0 || b.GetLength(0) == 0
|| a.GetLength(1) == 0 || b.GetLength(1) == 0)
{
return false;
}
return a.GetLength(1) == b.GetLength(0);
}
static int[,] MultiplySafe(int[,] a, int[,] b)
{
if (!CanMultiply(a, b))
{
return null;
}
int m = a.GetLength(0);
int n = a.GetLength(1);
int p = b.GetLength(1);
int[,] result = new int[m, p];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
for (int k = 0; k < n; k++)
{
result[i, j] += a[i, k] * b[k, j];
}
}
}
return result;
}
static string MatrixToString(int[,] m)
{
if (m == null)
{
return "null";
}
StringBuilder sb = new StringBuilder();
sb.Append("[");
int rows = m.GetLength(0);
int cols = m.GetLength(1);
for (int i = 0; i < rows; i++)
{
if (i > 0) sb.Append(", ");
sb.Append("[");
for (int j = 0; j < cols; j++)
{
if (j > 0) sb.Append(", ");
sb.Append(m[i, j]);
}
sb.Append("]");
}
sb.Append("]");
return sb.ToString();
}
static void Main()
{
int[,] ok = MultiplySafe(
new int[,] { { 1, 2, 3 }, { 4, 5, 6 } },
new int[,] { { 7, 8 }, { 9, 10 }, { 11, 12 } }
);
int[,] bad = MultiplySafe(
new int[,] { { 1, 2 }, { 3, 4 } },
new int[,] { { 5, 6, 7 } }
);
Console.WriteLine(MatrixToString(ok));
Console.WriteLine(MatrixToString(bad));
}
} First sample is 2×3 times 3×2 → 2×2. Second fails because columns of A (2) do not match rows of B (1).
Require cols(A) == rows(B); result will be rows(A) × cols(B).
Create an m×p matrix of zeros before accumulation.
For each i, j accumulate A[i, k] * B[k, j] over k.
C holds every row–column dot product.
Trace the first row of C for the Example 1 matrices.
| Cell | Dot product | Value |
|---|---|---|
C[0][0] | 1*9 + 2*6 + 3*3 | 30 |
C[0][1] | 1*8 + 2*5 + 3*2 | 24 |
C[0][2] | 1*7 + 2*4 + 3*1 | 18 |
First row of the result is [30, 24, 18] — matching Example 1 output.
Where true matrix multiplication shows up beyond the interview prompt.
2D indexing plus accumulation over k.
Example: write MultiplyMatrices(A, B).
Step up from addition/division to products.
Example: compare with Hadamard multiply.
Compose maps in graphics and simple ML.
Example: apply a 2×2 transform to points.
Practice (m×n)(n×p)→m×p checks.
Example: reject incompatible pairs.
State O(n³) for the classic square case.
Example: mention libraries for large n.
Next page returns to entrywise ops.
Example: continue the matrix chain.
Pro Tip: open with “(m×n)(n×p)→m×p, C[i, j] is a row–column dot product” before writing loops.
Why the classic triple-loop approach works well in interviews.
One rule: C[i, j] = sum of A[i, k] * B[k, j].
2×2 dry-runs verify understanding in seconds.
Inner-dimension checks are a natural follow-up question.
Same idea as a library multiply — you just write the loops by hand.
Pro Tip: lead with loops and zero-init; mention library helpers only as a production aside.
Small habits that keep matrix-multiplication solutions interview-ready.
Say (m×n)(n×p)→m×p before writing code.
Accumulation requires starting at zero.
Always pair A[i, k] with B[k, j].
Avoid [[0]*n]*n shared references.
Square vs rectangular complexity in one sentence.
Pro Tip: dry-run 1*5 + 2*7 = 19 aloud on the 2×2 sample — if that matches, your indexing is correct.
Mistakes that commonly break matrix-multiplication solutions.
Multiplying when cols(A) ≠ rows(B).
→ Validate shapes before looping.
Writing A[i, j] * B[i, j] instead of a dot product.
→ Use three loops and the k index.
Accumulating into uninitialized cells.
→ Start every C[i, j] at 0.
Order usually changes the result (or validity).
→ Multiply in the requested order only.
[[0]*n]*n shares row lists.
→ Build each row separately.
Common beginner mistakes — plus a few more.
Cannot multiply unless columns of A equal rows of B.
Changing order usually changes result, and sometimes makes multiplication invalid.
If result cells do not start at zero, accumulation gives incorrect values.
Validate GetLength(1) of A equals GetLength(0) of B before multiplying.
Still a product: C[0][0] = A[0][0] * B[0][0].
Use m, n, p — not a single N — when shapes differ.
Handy follow-ups interviewers sometimes ask.
Try these variations to lock in the pattern.
C[i, j] = sum(A[i, k] * B[k, j]), with compatible dimensions.rowsA, colsA, and colsB with the check colsA == rowsB.Quick Takeaway: compatible shapes first, zero-init C, then accumulate A[i, k]*B[k, j] with three nested loops.
| Setting | Time | Extra space |
|---|---|---|
Two n × n matrices, classic triple loop | O(n^3) | O(1) beyond output |
m × n by n × p | O(m*n*p) | O(1) beyond output |
| Shape validation | O(m + n) row checks | O(1) |
For large matrices, production code usually switches to optimized libraries; interviews still expect the triple-loop explanation.
Matrix multiplication builds each result cell as a row–column dot product when inner dimensions match. Zero-init the result, use three nested loops, and distinguish this from element-wise multiplication.
Practice the three examples above, then continue to matrix subtraction for the next entrywise operation.
Compatible shapes first, zero-init C, then C[i, j] += A[i, k] * B[k, j].
Multiply matrices the interview-friendly way.
Row · column
Definition(m×n)(n×p)
Constrainti, j, then k
PatternStart at zero
SafetyO(n³) / O(mnp)
AnalysisMatrix multiplication pairs rows of A with columns of B. If A is m x n and B is n x p, then AB exists and has size m x p.
Learn entrywise subtraction with matching dimensions — a simpler return to cell-by-cell ops.
8 people found this page helpful