Rotating an n×n matrix 90° clockwise in-place looks daunting, but decomposes neatly into two familiar operations: transpose (swap across the main diagonal), then reverse each row — no extra array needed.
Given an n×n matrix, rotate it 90° clockwise in-place — no allocating a new matrix.
Example: [[1,2,3],[4,5,6],[7,8,9]] → after rotation: [[7,4,1],[8,5,2],[9,6,3]]. The first column of the original becomes the first row of the result, bottom-to-top.
matrix[i][j] swaps with matrix[j][i]; then (2) reverse each row — mirror each row left-to-right. Each step touches every cell exactly once, so the combined cost is O(n²) with O(1) extra space.i from 0 to n-1, j from i+1 to n-1 (only the upper triangle, to avoid double-swapping). Swap matrix[i][j] ↔ matrix[j][i].i, use two pointers lo=0, hi=n-1; swap while lo < hi, then advance inward. This mirrors the row, completing the 90° rotation.j starts at 0 instead of i+1, each pair gets swapped twice — returning to the original matrix. Always start j at i+1.Both approaches are O(n²) time — every cell must move. The in-place approach is preferred in interviews because it demonstrates the decomposition insight and avoids the O(n²) auxiliary allocation. A third option is 4-way cycle rotation (rotate groups of four cells in concentric rings), which is also O(1) space but harder to implement without off-by-one errors.
function rotate(matrix: number[][]): void {
const n = matrix.length;
// Phase 1 — transpose: swap matrix[i][j] with matrix[j][i]
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
const tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
// Phase 2 — reverse each row
for (let i = 0; i < n; i++) {
let lo = 0, hi = n - 1;
while (lo < hi) {
const tmp = matrix[i][lo];
matrix[i][lo] = matrix[i][hi];
matrix[i][hi] = tmp;
lo++;
hi--;
}
}
}i; the inner loop starts at j = i + 1 so we only visit the upper triangle. Each iteration does a 3-variable swap of matrix[i][j] and matrix[j][i]. After this phase the matrix equals the mathematical transpose of the original.lo = 0 and hi = n - 1, swap, and move the pointers inward until they meet. Doing this for every row turns the transpose into a 90° clockwise rotation.[i][j] and once as [j][i]), undoing both swaps and leaving the matrix unchanged.| rotate matrix 90° clockwise in-place | transpose then reverse rows |
| flip matrix across main diagonal | swap [i][j] ↔ [j][i], j starts at i+1 |
| rotate counter-clockwise | reverse rows first, then transpose |
| in-place 2D transformation without extra space | decompose into two sweeps |
function rotate(matrix: number[][]): void {
const n = matrix.length;
// Phase 1: transpose
for (let i = 0; i < n; i++)
for (let j = i + 1; j < n; j++) {
[matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
}
// Phase 2: reverse each row
for (let i = 0; i < n; i++) {
let lo = 0, hi = n - 1;
while (lo < hi) {
[matrix[i][lo], matrix[i][hi]] = [matrix[i][hi], matrix[i][lo]];
lo++; hi--;
}
}
}j start at i + 1 rather than 0?[[1,2],[3,4]]. After 90° clockwise rotation, the result is: