DSA Guide
Matrix

Transpose Matrix

Flip a grid over its diagonal — the index swap that underlies rotation, and the loop bound that makes it work

EasyMatrix· reflect across the main diagonal
ArrayMatrixSimulation
Problem #867

Problem Statement

Return the transpose of a matrix: rows become columns and columns become rows.

Input:  [[1,2,3],
         [4,5,6],
         [7,8,9]]

Output: [[1,4,7],
         [2,5,8],
         [3,6,9]]

Input:  [[1,2,3],
         [4,5,6]]          2 rows, 3 columns

Output: [[1,4],
         [2,5],
         [3,6]]            3 rows, 2 columns

Intuition

The rule is one line: result[c][r] = grid[r][c]. Swap the two indices.

Visually, it is a reflection across the main diagonal — the line from top-left to bottom-right. Values on that diagonal do not move, because swapping r and c when they are equal changes nothing.

1 2 3          1 . .
4 5 6    →     . 5 .        the diagonal stays put
7 8 9          . . 9

The shape changes too

An m × n matrix transposes into an n × m one. For a 2×3 input the output has 3 rows and 2 columns.

This is why the general solution builds a new grid: you cannot reshape a rectangle in place. Only a square matrix can be transposed in place, which is the case Rotate Image relies on.

Approach

Measure both dimensions

rows = len(grid), cols = len(grid[0]). Do this first — the output uses them the other way round.

Build a cols × rows grid

Note the reversal. Using rows × cols fails on any non-square input.

Copy every cell to its swapped position

result[c][r] = grid[r][c].

Transposing a 2 × 3 matrix
012
0
1
2
3
1
4
5
6
sourcegrid[0][0] = 1targetresult[0][0]
Start at the top-left. Row 0, column 0 swaps to row 0, column 0 — unchanged, because it is on the diagonal.
1 / 4
Six cells, six copies. Each value moves to the position with its indices reversed.

Solution

def transpose(matrix: list[list[int]]) -> list[list[int]]:
    """Return the transpose: result[c][r] = matrix[r][c]."""
    rows, cols = len(matrix), len(matrix[0])
    result = [[0] * rows for _ in range(cols)]

    for r in range(rows):
        for c in range(cols):
            result[c][r] = matrix[r][c]

    return result

The output is built with [[0] * rows for _ in range(cols)]cols rows of length rows. Getting these the wrong way round is the main trap.

A one-liner exists: [list(row) for row in zip(*matrix)]. It is idiomatic and correct; the explicit loop is what shows the index swap.

The in-place version, and why `c` starts at `r`

For a square matrix you can swap pairs directly with no new grid:

for r in range(n):
    for c in range(r, n):          ← starts at r, not 0
        grid[r][c], grid[c][r] = grid[c][r], grid[r][c]

Starting c at 0 swaps every pair twice — once as (r,c) and again as (c,r) — returning the matrix exactly as it began.

That bug produces no error and no visible symptom except the output being the input. Starting at r visits each pair once and skips the diagonal, which never needs moving.

Complexity Analysis

Time Complexity

O(rows × cols)

Space Complexity

O(rows × cols)

Time — every cell is copied once. There is no way to do better; the output has that many cells.

Space — the new grid. The in-place square version is O(1), but it cannot handle rectangles.

Edge Cases

  • Rotate Image — transpose plus a row reversal gives a 90° rotation
  • Spiral Matrix — a different way of walking the same grid
  • Matrix — the index conventions and the reference trap

On this page