On this page
Description
Rotating a square matrix by 90 degrees in place is easiest as two simple moves. First transpose it, flipping it along the main diagonal. Then reverse each row, or reverse the order of the rows for the other direction. Each move is easy to check on its own, and that's the point. A one-formula version that moves every cell straight to its final place is much easier to get subtly wrong.
We'll go from simple to more technical:
- The pattern: transpose, then reverse.
- A second flavor: which axis you reverse decides the direction.
- Where composing simple transforms is how real image and matrix code is built.
- The mistakes that produce a plausible but wrong matrix.
The approach
Transposing swaps rows and columns: the value at row r, column c moves to row c, column r. The first column becomes the first row. Reversing each row then makes that row read from the other end. Together they give a clockwise turn.
With letters, so you can follow each one:
| Row | Original | After transposing | After reversing each row (clockwise) |
|---|---|---|---|
| 0 | a b c | a d g | g d a |
| 1 | d e f | b e h | h e b |
| 2 | g h i | c f i | i f c |
Check it: after a clockwise turn, the left column a d g, read from the bottom up, becomes the top row g d a.
Java
// Transpose: swap across the main diagonal (only the upper triangle needs visiting).
for (int r = 0; r < n; r++)
for (int c = r + 1; c < n; c++) {
int tmp = matrix[r][c];
matrix[r][c] = matrix[c][r];
matrix[c][r] = tmp;
}
// Reverse each row in place.
for (int[] row : matrix)
for (int i = 0, j = n - 1; i < j; i++, j--) {
int tmp = row[i]; row[i] = row[j]; row[j] = tmp;
}
Python
# Transpose: swap across the main diagonal (only the upper triangle needs visiting).
for r in range(n):
for c in range(r + 1, n):
matrix[r][c], matrix[c][r] = matrix[c][r], matrix[r][c]
# Reverse each row in place.
for row in matrix:
row.reverse()
The transpose loop starts c at r + 1, so it visits only the cells above the diagonal. Each pair is swapped exactly once.
A second flavor: which axis you reverse decides the direction
The transpose is the same for both directions. Only the second move changes. For counterclockwise, reverse the order of the rows and leave each row's contents alone:
Java
// Counterclockwise: transpose, then reverse the ORDER of rows (not each row's own contents).
for (int r = 0; r < n / 2; r++) {
int[] tmp = matrix[r];
matrix[r] = matrix[n - 1 - r];
matrix[n - 1 - r] = tmp;
}
Python
# Counterclockwise: transpose, then reverse the ORDER of rows (not each row's own contents).
for r in range(n // 2):
matrix[r], matrix[n - 1 - r] = matrix[n - 1 - r], matrix[r]
The transposed letters a d g / b e h / c f i become c f i / b e h / a d g. Mixing the two up doesn't crash or make garbage. It produces a perfectly valid rotation in the other direction, which is why the bug is easy to miss.
Where you'll see it
Image and matrix libraries are built this way. A thumbnail rotation, for example, is assembled from small steps such as transpose and flip, each tested on its own. Breaking one hard transform into two easy ones is a habit worth keeping well beyond matrices.
Which tool for which job?
| You need | Use |
|---|---|
| 90 degrees clockwise, in place | transpose, then reverse each row |
| 90 degrees counterclockwise, in place | transpose, then reverse the row order |
| 180 degrees | reverse the row order and each row |
| Fewest writes, in place | four-way cycles, layer by layer |
| A non-square matrix | a new n x m matrix: out[c][rows-1-r] = m[r][c] |
| A quick copy in Python | zip(*m[::-1]) |
Common mistakes
| Mistake | What happens | Do this instead |
|---|---|---|
Transposing every pair (c from 0) | each pair is swapped twice; nothing changes | c from r + 1 |
| Reversing the wrong axis | the opposite rotation | trace a 2x2 by hand |
| Reversing without transposing | a reflection, not a rotation | transpose first |
| Rotating a non-square matrix in place | it doesn't fit | allocate the rotated shape |
| Off-by-one in the four-way cycle | cells land in the wrong ring | loop i from layer to n - 2 - layer |
Check yourself
Try to answer before opening each one - recalling beats re-reading.
1. A transpose loop visits every pair (r, c), not just those with c > r. What happens?
Show answer
Each pair is swapped, then swapped back when the loop reaches its mirror image. The matrix ends exactly as it started, with no error and no sign that anything went wrong.
2. For a counterclockwise turn, a solution transposes and then reverses each row. What's the result?
Show answer
A valid 90-degree rotation, but clockwise. Nothing crashes and nothing looks broken. Only a test with distinct values in a known layout can tell the two directions apart.
3. Transpose-then-reverse makes two passes. Why prefer it to a one-pass index formula?
Show answer
Each pass is simple, well known and easy to check on its own. A single combined formula has to get every index and offset right at once, with nothing to check halfway. The extra pass is a small cost; a wrong formula is easy to write and hard to spot.
Key takeaways
- Rotate in two passes: transpose, then reverse. No index formula is needed.
- Transpose only the cells above the diagonal (
c > r), or every swap is undone. - After the transpose, reversing each row turns clockwise; reversing the row order turns counterclockwise.
- Every bug here gives a believable matrix rather than a crash. Test with distinct values you can check by hand.