167 lines
6.4 KiB
YAML
167 lines
6.4 KiB
YAML
title: Rotate Image
|
||
slug: rotate-image
|
||
difficulty: medium
|
||
leetcode_id: 48
|
||
leetcode_url: https://leetcode.com/problems/rotate-image/
|
||
categories:
|
||
- arrays
|
||
- math
|
||
patterns:
|
||
- matrix-manipulation
|
||
|
||
description: |
|
||
You are given an `n × n` 2D matrix representing an image. Rotate the image by **90 degrees** (clockwise).
|
||
|
||
You have to rotate the image **in-place**, which means you have to modify the input 2D matrix directly. **DO NOT** allocate another 2D matrix and do the rotation.
|
||
|
||
constraints: |
|
||
- `n == matrix.length == matrix[i].length`
|
||
- `1 <= n <= 20`
|
||
- `-1000 <= matrix[i][j] <= 1000`
|
||
|
||
examples:
|
||
- input: "matrix = [[1,2,3],[4,5,6],[7,8,9]]"
|
||
output: "[[7,4,1],[8,5,2],[9,6,3]]"
|
||
explanation: "The 3×3 matrix is rotated 90 degrees clockwise."
|
||
- input: "matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]"
|
||
output: "[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]"
|
||
explanation: "The 4×4 matrix is rotated 90 degrees clockwise."
|
||
|
||
explanation:
|
||
intuition: |
|
||
Rotating a matrix 90° clockwise might seem like it requires complex index manipulation, but there's a beautiful mathematical insight: the rotation can be decomposed into **two simple operations**.
|
||
|
||
Think of it like this: a 90° clockwise rotation moves element at position `(i, j)` to position `(j, n-1-i)`. This transformation happens to be equivalent to:
|
||
1. **Transpose** the matrix (swap rows and columns)
|
||
2. **Reverse** each row
|
||
|
||
Visually for a 3×3 matrix:
|
||
```
|
||
Original Transpose Reverse rows
|
||
1 2 3 1 4 7 7 4 1
|
||
4 5 6 → 2 5 8 → 8 5 2
|
||
7 8 9 3 6 9 9 6 3
|
||
```
|
||
|
||
Both operations can be done in-place with simple swaps, making this the cleanest approach.
|
||
|
||
approach: |
|
||
We solve this using **Transpose + Reverse**:
|
||
|
||
**Step 1: Transpose the matrix**
|
||
|
||
- Swap `matrix[i][j]` with `matrix[j][i]` for all `i < j`
|
||
- Only iterate over the upper triangle (`j > i`) to avoid undoing swaps
|
||
- After this, rows become columns and vice versa
|
||
|
||
|
||
|
||
**Step 2: Reverse each row**
|
||
|
||
- For each row, reverse the order of elements
|
||
- Python's `row.reverse()` does this in-place
|
||
|
||
|
||
|
||
**Why does this work?**
|
||
|
||
- Transpose: `(i, j) → (j, i)`
|
||
- Reverse row: `(j, i) → (j, n-1-i)`
|
||
- Combined: `(i, j) → (j, n-1-i)` — exactly 90° clockwise rotation!
|
||
|
||
|
||
|
||
This decomposition turns a complex problem into two simple, understandable operations.
|
||
|
||
common_pitfalls:
|
||
- title: Transposing the Entire Matrix Twice
|
||
description: |
|
||
When transposing, only swap elements in the **upper triangle** (where `j > i`). If you iterate over all pairs, you'll swap `(i,j)` and then `(j,i)` — undoing the first swap!
|
||
|
||
The inner loop should start at `j = i + 1`, not `j = 0`.
|
||
wrong_approach: "for j in range(n): swap (i,j) and (j,i)"
|
||
correct_approach: "for j in range(i + 1, n): swap (i,j) and (j,i)"
|
||
|
||
- title: Confusing Clockwise and Counterclockwise
|
||
description: |
|
||
- **Clockwise 90°**: Transpose, then reverse each row
|
||
- **Counterclockwise 90°**: Transpose, then reverse each column (or reverse rows first, then transpose)
|
||
|
||
Getting this wrong rotates in the opposite direction.
|
||
wrong_approach: "Reversing columns for clockwise rotation"
|
||
correct_approach: "Transpose + reverse rows = clockwise"
|
||
|
||
- title: Allocating Extra Space
|
||
description: |
|
||
The problem explicitly requires in-place rotation. Both transpose and row reversal can be done with swaps using O(1) extra space.
|
||
|
||
Creating a new matrix and copying values violates the constraint.
|
||
wrong_approach: "Creating a new n×n matrix for the result"
|
||
correct_approach: "Use in-place swaps only"
|
||
|
||
key_takeaways:
|
||
- "**Decompose complex transformations**: 90° rotation = transpose + reverse"
|
||
- "**Upper triangle only for transpose**: Avoid undoing swaps by only iterating where `j > i`"
|
||
- "**Know your rotations**: Clockwise vs counterclockwise requires different orderings"
|
||
- "**In-place operations are possible**: Most matrix transformations can be done with careful swapping"
|
||
|
||
time_complexity: "O(n²). We visit each element a constant number of times during transpose and reversal."
|
||
space_complexity: "O(1). All operations are done in-place using only swaps."
|
||
|
||
solutions:
|
||
- approach_name: Transpose + Reverse
|
||
is_optimal: true
|
||
code: |
|
||
def rotate(matrix: list[list[int]]) -> None:
|
||
n = len(matrix)
|
||
|
||
# Step 1: Transpose (swap across main diagonal)
|
||
# Only iterate upper triangle to avoid undoing swaps
|
||
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 each row
|
||
for row in matrix:
|
||
row.reverse()
|
||
explanation: |
|
||
**Time Complexity:** O(n²) — Visit each element constant times.
|
||
|
||
**Space Complexity:** O(1) — In-place swaps only.
|
||
|
||
Transpose swaps elements across the main diagonal, converting rows to columns. Reversing each row then completes the 90° clockwise rotation. Both operations are simple and in-place.
|
||
|
||
- approach_name: Layer-by-Layer Rotation
|
||
is_optimal: false
|
||
code: |
|
||
def rotate(matrix: list[list[int]]) -> None:
|
||
n = len(matrix)
|
||
|
||
# Rotate layer by layer from outside to inside
|
||
for layer in range(n // 2):
|
||
first, last = layer, n - 1 - layer
|
||
|
||
for i in range(first, last):
|
||
offset = i - first
|
||
|
||
# Save top element
|
||
top = matrix[first][i]
|
||
|
||
# Move left → top
|
||
matrix[first][i] = matrix[last - offset][first]
|
||
|
||
# Move bottom → left
|
||
matrix[last - offset][first] = matrix[last][last - offset]
|
||
|
||
# Move right → bottom
|
||
matrix[last][last - offset] = matrix[i][last]
|
||
|
||
# Move top → right (using saved value)
|
||
matrix[i][last] = top
|
||
explanation: |
|
||
**Time Complexity:** O(n²) — Visit each element once.
|
||
|
||
**Space Complexity:** O(1) — Only one temp variable.
|
||
|
||
Rotate the matrix layer by layer, from the outermost ring inward. For each position in a layer, perform a four-way swap moving elements clockwise. Correct but more complex to implement and understand than transpose+reverse.
|