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 JavaScript 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 | 2D arrays | 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 matMul helpers | 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 | Array.from({ length: n }, () => Array(n).fill(0)) |
| Shape check | a[0].length === b.length (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
matMul(A, B)Fast 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 JavaScript 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.
const N = 3;
function multiplyMatrices(a, b) {
const result = [];
for (let i = 0; i < N; i++) {
result[i] = [];
for (let j = 0; j < N; j++) {
result[i][j] = 0;
}
}
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
for (let k = 0; k < N; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
function displayMatrix(matrix) {
for (let i = 0; i < N; i++) {
console.log(matrix[i].join("\t"));
}
}
const firstMatrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const secondMatrix = [
[9, 8, 7],
[6, 5, 4],
[3, 2, 1],
];
const result = multiplyMatrices(firstMatrix, secondMatrix);
console.log("First Matrix:");
displayMatrix(firstMatrix);
console.log("\nSecond Matrix:");
displayMatrix(secondMatrix);
console.log("\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.
const N = 2;
function multiplyMatrices(a, b) {
const result = [];
for (let i = 0; i < N; i++) {
result[i] = [];
for (let j = 0; j < N; j++) {
result[i][j] = 0;
for (let k = 0; k < N; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
function printMatrix(title, m) {
console.log(title);
for (let i = 0; i < N; i++) {
console.log(m[i].join(" "));
}
}
const a = [[1, 2], [3, 4]];
const b = [[5, 6], [7, 8]];
const r = multiplyMatrices(a, b);
printMatrix("A", a);
console.log();
printMatrix("B", b);
console.log();
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.
function canMultiply(a, b) {
if (!a.length || !b.length || !a[0].length || !b[0].length) {
return false;
}
const colsA = a[0].length;
const rowsB = b.length;
if (colsA !== rowsB) {
return false;
}
const colsB = b[0].length;
for (let i = 0; i < a.length; i++) {
if (a[i].length !== colsA) {
return false;
}
}
for (let i = 0; i < b.length; i++) {
if (b[i].length !== colsB) {
return false;
}
}
return true;
}
function multiplySafe(a, b) {
if (!canMultiply(a, b)) {
return null;
}
const m = a.length;
const n = a[0].length;
const p = b[0].length;
const result = Array.from({ length: m }, () => Array(p).fill(0));
for (let i = 0; i < m; i++) {
for (let j = 0; j < p; j++) {
for (let k = 0; k < n; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
const ok = multiplySafe([[1, 2, 3], [4, 5, 6]], [[7, 8], [9, 10], [11, 12]]);
const bad = multiplySafe([[1, 2], [3, 4]], [[5, 6, 7]]);
console.log(JSON.stringify(ok));
console.log(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 a library helper 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 library matrix helpers — 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 every row length 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.
null or throwC[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 links rows of A with columns of B. You need A to be m × n and B to be n × p—the two n’s must match—then AB is m × p.
Learn entrywise subtraction with matching dimensions — a simpler return to cell-by-cell ops.
8 people found this page helpful