Odd-sized matrices
The center element sits on the main diagonal. The transpose skips it (r == c), and the row-reverse places it at the midpoint — it stays put naturally.
A photo editor rotates a square image 90° clockwise without allocating a second canvas. The trick: decompose the rotation into two mechanical steps — transpose the pixel grid across the main diagonal, then mirror each row left-to-right. Each step overwrites in place using a single swap variable. O(n²) time. O(1) extra space.
Transpose reflects the matrix across its main diagonal: every cell [r][c] swaps with [c][r]. Rows become columns and columns become rows.
Reverse each row then mirrors every row horizontally — a two-pointer sweep from the edges inward. Composing these two reflections produces exactly a 90° clockwise rotation.
A 90° clockwise rotation decomposes into two reflections: transpose (mirror across the diagonal), then reverse each row (mirror horizontally). No extra space beyond a single swap variable.
Swap every cell [r][c] with [c][r] for all c > r. This reflects the matrix across its main diagonal.
For each row, use a two-pointer sweep from the edges inward, swapping [row][left] with [row][right].
Understanding boundary behavior is as important as the main algorithm path.
The center element sits on the main diagonal. The transpose skips it (r == c), and the row-reverse places it at the midpoint — it stays put naturally.
Both phases produce zero iterations. The single element is already its own rotation.
Transpose then reverse → clockwise. Reverse then transpose → counter-clockwise. The order is not interchangeable.
Time: O(n²) — each cell is visited at most twice
(once during transpose, once during reverse).
Space: O(1) — all swaps are performed in place.