48. Rotate Image
On LeetCode ->Reformulated question¶
Rotate an n x n matrix 90 degrees clockwise, in place.
Compact example:
Key trick¶
Use one of these in-place views of the same transform:
- Transpose, then reverse each row.
- Or rotate 4 cells at a time by layers.
The interview-friendly trick is:
(r, c)becomes(c, n - 1 - r)- Implement it as:
- swap across the diagonal
- reverse each row
Trap¶
Common mistakes:
- Building a new matrix, which breaks the in-place requirement.
- Reversing columns instead of rows.
- Getting transpose indices wrong.
- Forgetting odd-size center stays unchanged.
- In tests, using a shallow copy like
matrix[:], which shares inner lists.
Why is this question interesting?¶
It tests whether you can:
- See a geometric transform as index manipulation.
- Turn a hard-looking in-place update into two simple in-place steps.
- Avoid mutation bugs in 2D lists.
Solve the problem with idiomatic python¶
class Solution:
def rotate(self, matrix: list[list[int]]) -> None:
n = len(matrix)
# Transpose in place: swap matrix[r][c] with matrix[c][r]
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()
If you want the shortest equivalent row-reversal step:
But row.reverse() is more clearly in place.
Pytest test¶
import pytest
@pytest.mark.parametrize(
("matrix", "expected"),
[
(
[[1]],
[[1]],
),
(
[[1, 2], [3, 4]],
[[3, 1], [4, 2]],
),
(
[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
[[7, 4, 1], [8, 5, 2], [9, 6, 3]],
),
(
[[5, 1, 9, 11], [2, 4, 8, 10], [13, 3, 6, 7], [15, 14, 12, 16]],
[[15, 13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7, 10, 11]],
),
(
[[-1, -2], [-3, -4]],
[[-3, -1], [-4, -2]],
),
],
)
def test_rotate(matrix, expected):
m = [row[:] for row in matrix]
Solution().rotate(m)
assert m == expected
Comment my solution¶
Your solution works, but it is not the best interview answer.
Main issues:
- It uses extra arrays for each layer:
ab,bc,cd,da
- That is still not another full matrix, but it is more complex than needed.
- The layer logic is harder to verify and explain under pressure.
- The test uses
matrix[:], which is a shallow copy and is unsafe for 2D lists.
What to improve:
- Prefer transpose + reverse rows:
- shorter
- easier to prove
- truly in place
- Fix the test copy with:
import pytest
class Solution:
def rotate(self, matrix: list[list[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
# matrix[i][j] -> a[j, n - 1 - i]
n = len(matrix)
for k in range((n // 2)):
# box k
box_len = n - 2 * k
low = k
high = k + box_len - 1
box_range = range(k, k + box_len)
ab = [matrix[low][j] for j in box_range]
bc = [matrix[i][high] for i in box_range]
cd = [matrix[high][j] for j in reversed(box_range)]
da = [matrix[i][low] for i in reversed(box_range)]
# ab -> bc
for idx, i in enumerate(box_range):
matrix[i][high] = ab[idx]
# bc -> cd
for idx, j in enumerate(reversed(box_range)):
matrix[high][j] = bc[idx]
# cd -> da
for idx, i in enumerate(reversed(box_range)):
matrix[i][low] = cd[idx]
# da -> ab
for idx, j in enumerate(box_range):
matrix[low][j] = da[idx]
return None
@pytest.mark.parametrize(
("matrix", "expected"),
[
([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],
[[7, 4, 1],
[8, 5, 2],
[9, 6, 3]]),
(
[[ 5, 1, 9, 11],
[ 2, 4, 8, 10],
[13, 3, 6, 7],
[15, 14, 12, 16]],
[[15, 13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7, 10, 11]],
),
],
) # fmt: skip
def test_rotate(matrix, expected):
m = matrix[:]
Solution().rotate(m)
assert m == expected