188 lines
8.4 KiB
YAML
188 lines
8.4 KiB
YAML
title: Transpose Matrix
|
||
slug: transpose-matrix
|
||
difficulty: easy
|
||
leetcode_id: 867
|
||
leetcode_url: https://leetcode.com/problems/transpose-matrix/
|
||
categories:
|
||
- arrays
|
||
patterns:
|
||
- slug: matrix-traversal
|
||
is_optimal: true
|
||
|
||
function_signature: "def transpose(matrix: list[list[int]]) -> list[list[int]]:"
|
||
|
||
test_cases:
|
||
visible:
|
||
- input: { matrix: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] }
|
||
expected: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
||
- input: { matrix: [[1, 2, 3], [4, 5, 6]] }
|
||
expected: [[1, 4], [2, 5], [3, 6]]
|
||
hidden:
|
||
- input: { matrix: [[1]] }
|
||
expected: [[1]]
|
||
- input: { matrix: [[1, 2], [3, 4]] }
|
||
expected: [[1, 3], [2, 4]]
|
||
- input: { matrix: [[1], [2], [3]] }
|
||
expected: [[1, 2, 3]]
|
||
- input: { matrix: [[1, 2, 3, 4]] }
|
||
expected: [[1], [2], [3], [4]]
|
||
|
||
description: |
|
||
Given a 2D integer array `matrix`, return *the **transpose** of* `matrix`.
|
||
|
||
The **transpose** of a matrix is the matrix flipped over its main diagonal, switching the matrix's row and column indices.
|
||
|
||
In other words, for every element at position `matrix[i][j]`, its transposed position becomes `result[j][i]`.
|
||
|
||
constraints: |
|
||
- `m == matrix.length`
|
||
- `n == matrix[i].length`
|
||
- `1 <= m, n <= 1000`
|
||
- `1 <= m * n <= 10^5`
|
||
- `-10^9 <= matrix[i][j] <= 10^9`
|
||
|
||
examples:
|
||
- input: "matrix = [[1,2,3],[4,5,6],[7,8,9]]"
|
||
output: "[[1,4,7],[2,5,8],[3,6,9]]"
|
||
explanation: "The 3x3 matrix is flipped along its main diagonal. Row 0 becomes column 0, row 1 becomes column 1, etc."
|
||
- input: "matrix = [[1,2,3],[4,5,6]]"
|
||
output: "[[1,4],[2,5],[3,6]]"
|
||
explanation: "The 2x3 matrix becomes a 3x2 matrix. Each row of the original becomes a column in the result."
|
||
|
||
explanation:
|
||
intuition: |
|
||
Imagine physically rotating a matrix 90 degrees clockwise, then flipping it horizontally — that's essentially what transposing does, but there's an easier way to think about it.
|
||
|
||
Picture each element in the matrix as having a "home address" of `(row, column)`. When you transpose, every element simply **swaps its row and column indices**. The element at `(0, 2)` moves to `(2, 0)`. The element at `(1, 0)` moves to `(0, 1)`.
|
||
|
||
Think of it like this: if you were reading the original matrix row by row from left to right, the transposed matrix reads the original *column by column* from top to bottom.
|
||
|
||
The key insight is that a matrix with dimensions `m × n` becomes `n × m` after transposition. This means we need to create a **new matrix** with swapped dimensions — we can't just rearrange elements in place (unless the matrix is square).
|
||
|
||
approach: |
|
||
We solve this using a **Direct Mapping Approach**:
|
||
|
||
**Step 1: Determine the dimensions**
|
||
|
||
- Get `m` (number of rows) and `n` (number of columns) from the original matrix
|
||
- The result will have dimensions `n × m` (rows and columns swapped)
|
||
|
||
|
||
|
||
**Step 2: Create the result matrix**
|
||
|
||
- Initialise a new matrix with `n` rows and `m` columns
|
||
- This can be done by creating `n` empty lists, each eventually containing `m` elements
|
||
|
||
|
||
|
||
**Step 3: Copy elements with swapped indices**
|
||
|
||
- Iterate through each element in the original matrix at position `(i, j)`
|
||
- Place it in the result matrix at position `(j, i)`
|
||
- This naturally swaps rows and columns
|
||
|
||
|
||
|
||
**Step 4: Return the transposed matrix**
|
||
|
||
- After processing all elements, return the result matrix
|
||
|
||
|
||
|
||
This approach works because the mathematical definition of transpose is exactly this index swap: `result[j][i] = matrix[i][j]` for all valid `i` and `j`.
|
||
|
||
common_pitfalls:
|
||
- title: Confusing Transpose with Rotation
|
||
description: |
|
||
A common mistake is thinking transpose means rotating 90 degrees. They're related but different:
|
||
|
||
- **Transpose**: Swap row and column indices — `(i,j)` → `(j,i)`
|
||
- **Rotate 90° clockwise**: More complex — `(i,j)` → `(j, m-1-i)`
|
||
|
||
For a 3x3 matrix `[[1,2,3],[4,5,6],[7,8,9]]`:
|
||
- Transpose gives `[[1,4,7],[2,5,8],[3,6,9]]`
|
||
- 90° rotation gives `[[7,4,1],[8,5,2],[9,6,3]]`
|
||
wrong_approach: "Applying rotation logic instead of index swap"
|
||
correct_approach: "Simply swap indices: result[j][i] = matrix[i][j]"
|
||
|
||
- title: In-Place Modification for Non-Square Matrices
|
||
description: |
|
||
With a square matrix (`n × n`), you might be tempted to swap elements in place. But for a non-square matrix (`m × n` where `m ≠ n`), the dimensions change!
|
||
|
||
A `2 × 3` matrix becomes `3 × 2`. You cannot do this in place because the result has a different shape than the input. Always create a new matrix with the transposed dimensions.
|
||
wrong_approach: "Trying to swap elements in place for m × n matrix"
|
||
correct_approach: "Create a new n × m matrix and map elements"
|
||
|
||
- title: Wrong Dimension Order
|
||
description: |
|
||
When creating the result matrix, remember the dimensions flip. If the original is `m` rows by `n` columns, the result is `n` rows by `m` columns.
|
||
|
||
Getting this wrong leads to index out of bounds errors or incorrectly shaped output.
|
||
wrong_approach: "Creating result with same dimensions as input"
|
||
correct_approach: "Result dimensions are (n, m) when input is (m, n)"
|
||
|
||
key_takeaways:
|
||
- "**Index swapping pattern**: Transposition is simply `result[j][i] = matrix[i][j]` — a fundamental matrix operation"
|
||
- "**Dimension awareness**: Always consider how matrix operations change dimensions — transpose swaps `m × n` to `n × m`"
|
||
- "**Foundation for linear algebra**: Transpose is essential for operations like computing dot products, matrix multiplication, and solving linear systems"
|
||
- "**Applicable to many problems**: Understanding matrix traversal patterns helps with rotation, spiral order, and diagonal traversal problems"
|
||
|
||
time_complexity: "O(m × n). We visit each element in the matrix exactly once to copy it to the new position."
|
||
space_complexity: "O(m × n). We create a new matrix to store the transposed result, which has the same total number of elements."
|
||
|
||
solutions:
|
||
- approach_name: Direct Mapping
|
||
is_optimal: true
|
||
code: |
|
||
def transpose(matrix: list[list[int]]) -> list[list[int]]:
|
||
# Get original dimensions
|
||
m, n = len(matrix), len(matrix[0])
|
||
|
||
# Create result matrix with swapped dimensions (n rows, m columns)
|
||
# Each position result[j][i] will hold matrix[i][j]
|
||
result = [[0] * m for _ in range(n)]
|
||
|
||
# Copy each element with swapped indices
|
||
for i in range(m):
|
||
for j in range(n):
|
||
result[j][i] = matrix[i][j]
|
||
|
||
return result
|
||
explanation: |
|
||
**Time Complexity:** O(m × n) — We iterate through every element once.
|
||
|
||
**Space Complexity:** O(m × n) — We store all elements in a new matrix.
|
||
|
||
This is optimal because we must at minimum read every element and write every element to produce the output, which requires O(m × n) operations.
|
||
|
||
- approach_name: List Comprehension (Pythonic)
|
||
is_optimal: true
|
||
code: |
|
||
def transpose(matrix: list[list[int]]) -> list[list[int]]:
|
||
# zip(*matrix) unpacks rows and zips them column-wise
|
||
# Each tuple from zip becomes a row in the transposed matrix
|
||
return [list(row) for row in zip(*matrix)]
|
||
explanation: |
|
||
**Time Complexity:** O(m × n) — Same as direct mapping, just more concise.
|
||
|
||
**Space Complexity:** O(m × n) — Creates a new matrix for the result.
|
||
|
||
This Pythonic approach uses `zip(*matrix)` to unpack the matrix rows and re-group elements by column index. The `*` operator unpacks the rows, and `zip` collects elements at the same position from each row — exactly what transpose does. We convert each tuple to a list for the final result.
|
||
|
||
- approach_name: Using NumPy
|
||
is_optimal: true
|
||
code: |
|
||
import numpy as np
|
||
|
||
def transpose(matrix: list[list[int]]) -> list[list[int]]:
|
||
# NumPy provides a built-in transpose operation
|
||
# .T is shorthand for np.transpose()
|
||
return np.array(matrix).T.tolist()
|
||
explanation: |
|
||
**Time Complexity:** O(m × n) — NumPy optimises the operation internally.
|
||
|
||
**Space Complexity:** O(m × n) — Creates the result array.
|
||
|
||
While not typically allowed in coding interviews, this shows how common matrix transpose is — it's built into numerical computing libraries. NumPy's `.T` attribute returns a transposed view of the array, and `tolist()` converts it back to a Python list of lists.
|