Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Matrix Rotation
DSA

Matrix Rotation

Learn efficient techniques for rotating square matrices in place.

Matrix rotation decomposes into two simple operations:

90° clockwise = Transpose → Reverse every row

Focus on recognizing:

“Rotate in place / no extra matrix” → compose transpose with reversals


Core Template: 90° Clockwise

public void rotateClockwise(int[][] matrix) {
    int n = matrix.length;

    // Step 1: Transpose (swap across main diagonal)
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }

    // Step 2: Reverse every row
    for (int i = 0; i < n; i++) {
        int left = 0;
        int right = n - 1;

        while (left < right) {
            int temp = matrix[i][left];
            matrix[i][left] = matrix[i][right];
            matrix[i][right] = temp;

            left++;
            right--;
        }
    }
}
def rotate_clockwise(matrix):
    n = len(matrix)

    # Step 1: Transpose
    for i in range(n):
        for j in range(i + 1, n):
            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

    # Step 2: Reverse every row
    for row in matrix:
        row.reverse()
void rotateClockwise(vector<vector<int>>& matrix) {
    int n = matrix.size();

    // Step 1: Transpose
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            swap(matrix[i][j], matrix[j][i]);

    // Step 2: Reverse every row
    for (auto& row : matrix)
        reverse(row.begin(), row.end());
}
function rotateClockwise(matrix) {
  const n = matrix.length;

  // Step 1: Transpose
  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
    }
  }

  // Step 2: Reverse every row
  for (const row of matrix) row.reverse();
}

90° CW → Transpose + Reverse Rows · 90° CCW → Transpose + Reverse Columns (or reverse rows first, then transpose).


Pattern: Transpose In Place

Watch the transpose swap mirror pairs across the diagonal, then rows flip — [1..9] becomes [[7,4,1],[8,5,2],[9,6,3]]. Press to animate.

Rotate Image 90° Clockwise (In-Place)

Rotate an n×n matrix 90° clockwise in place: first transpose across the main diagonal, then reverse every row. O(1) extra space.

Matrix: [[1,2,3],[4,5,6],[7,8,9]] → [[7,4,1],[8,5,2],[9,6,3]]. Transpose mirrors across the main diagonal (1,5,9 stay put), swapping the three mirror pairs; then reverse each row. The highlighted cells are the pair currently being swapped.

GRID VISUALIZER
Steps
1
2
3
4
5
6
7
8
9
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        transpose: for i<j swap M[i][j] ↔ M[j][i]
                      
                        2
                          pairs: (0,1)↔(1,0), (0,2)↔(2,0), (1,2)↔(2,1)
                      
                        3
                        reverse each row
                      
                        4
                        result: [[7,4,1],[8,5,2],[9,6,3]]
                      

The building block — note the inner loop starts at i + 1 so each pair swaps exactly once:

public void transpose(int[][] matrix) {
    int n = matrix.length;

    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
}
def transpose(matrix):
    n = len(matrix)

    for i in range(n):
        for j in range(i + 1, n):
            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
void transpose(vector<vector<int>>& matrix) {
    int n = matrix.size();

    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            swap(matrix[i][j], matrix[j][i]);
}
function transpose(matrix) {
  const n = matrix.length;

  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
    }
  }
}

Starting j at i + 1 matters — starting at 0 transposes twice (a no-op).


Other Rotations from the Same Pieces

90° counter-clockwise : transpose → reverse each COLUMN
180°                  : reverse each row → reverse each column
                       (or transpose twice + reverse rows)
public void rotate180(int[][] matrix) {
    int n = matrix.length, m = matrix[0].length;

    for (int i = 0; i < n; i++) {              // reverse rows
        for (int l = 0, r = m - 1; l < r; l++, r--) {
            int t = matrix[i][l];
            matrix[i][l] = matrix[i][r];
            matrix[i][r] = t;
        }
    }

    for (int j = 0; j < m; j++) {              // reverse columns
        for (int t = 0, b = n - 1; t < b; t++, b--) {
            int tmp = matrix[t][j];
            matrix[t][j] = matrix[b][j];
            matrix[b][j] = tmp;
        }
    }
}
def rotate_180(matrix):
    for row in matrix:
        row.reverse()          # reverse rows

    matrix.reverse()           # reverse row order (= columns)
void rotate180(vector<vector<int>>& matrix) {
    for (auto& row : matrix)                 // reverse rows
        reverse(row.begin(), row.end());

    reverse(matrix.begin(), matrix.end());   // reverse columns
}
function rotate180(matrix) {
  for (const row of matrix) row.reverse(); // reverse rows
  matrix.reverse(); // reverse row order (= columns)
}

Common Mistakes

Transposing twice by accident.

Inner loop must start at j = i + 1. Starting at j = 0 swaps every pair back.


Confusing CW and CCW recipes.

CW = transpose then reverse ROWS. CCW = transpose then reverse COLUMNS. Mixing them rotates the wrong way.


Rotating non-square matrices in place.

Transpose+reverse only works in place for square matrices — rectangular ones need a new grid.


Complexity

OperationTimeSpace
TransposeO(n²)O(1)
90° / 180°O(n²)O(1)

My Private Notes

Notes are auto-saved locally to this device.