33. Rotate Dashboard Matrix
Problem
An ops dashboard lays out N metrics widgets in an N x N grid. When the UI orientation changes, the entire layout needs to rotate 90 degrees clockwise, without allocating a second full matrix, since the grid can be large and this runs on every orientation change.
The function mutates matrix in place (e.g. transpose then reverse each row, or
layer-by-layer rotation), using O(1) extra space (aside from the input itself) and O(n²)
time. It returns nothing; the caller inspects the mutated matrix.
Source: src/33_rotate_dashboard_matrix.py
def rotate(matrix: list[list[int]]) -> None:
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> rotate(m)
>>> m
[[7, 4, 1], [8, 5, 2], [9, 6, 3]]
Step-by-Step Approach
- Recognize that a 90-degree clockwise rotation can be decomposed into two simpler, well-known in-place operations: transpose, then reverse each row.
- Transpose the matrix in place by swapping
matrix[i][j]withmatrix[j][i]for every pair wherej > i(only the upper triangle, to avoid swapping each pair back). - After the transpose, each row of the matrix currently holds what will become that row of the rotated matrix, but in reverse column order.
- Reverse each row in place (
row.reverse()) to finish the rotation. - Handle the trivial cases (empty matrix, 1x1 matrix) — they fall out naturally since the loops simply don't execute.
The key insight is that "rotate 90° clockwise" decomposes into "transpose" (reflect across the main diagonal) followed by "reverse each row" (reflect across the vertical axis) — two reflections compose into the rotation, and both are doable in place with only pairwise swaps.
Reference solution
def rotate(matrix: list[list[int]]) -> None:
# transpose in place, then reverse each row, O(n^2) time, O(1) extra space
n = len(matrix)
for i in range(n):
# upper triangle only, avoids swapping back
for j in range(i + 1, n):
# tuple-swap, no temp var
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
for row in matrix:
# flips column order to finish the rotation
row.reverse()
Key Functions & Tricks
a, b = b, a— Python's tuple-swap idiom, no temp variable needed.range(i + 1, n)for the inner loop — upper-triangle-only swap so each pair swaps exactly once.list.reverse()— reverses a list in place, returnsNone.- Transpose + row-reverse — two reflections that compose into a 90° clockwise rotation, O(n²) time, O(1) space.
How to Recognize This Pattern
Signals: "rotate a square matrix in place," "no extra matrix allowed," "O(1) extra space."
Any time an interviewer specifically forbids allocating a new grid, they're pointing you at
the transpose-then-reverse (or layer-by-layer four-way swap) technique rather than the
naive "build a new rotated matrix and copy it back" approach. Variations: (1) rotate
counter-clockwise instead — reverse each row before transposing, or transpose then reverse
columns instead of rows; (2) rotate by an arbitrary multiple of 90° — reduce
k % 4 and repeat, or handle 180°/270° with direct index math. A common
pitfall is transposing over the full matrix instead of just the upper triangle
(j > i), which swaps every pair twice and silently undoes the transpose.