Skip to content

48. Rotate Image

On LeetCode ->

Reformulated question

Rotate an n x n matrix 90 degrees clockwise, in place.

Compact example:

in:
1 2 3
4 5 6
7 8 9

out:
7 4 1
8 5 2
9 6 3

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:

for row in matrix:
    row[:] = row[::-1]

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:
m = [row[:] for row in matrix]
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