旋转图像
在 LeetCode 上查看 ↗语音讲解
开车或通勤时可听,跟着思路走一遍
题目描述
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1
示例 2
模拟答题者思考
1. 最直接:开一个新 n×n 数组,按公式 new[j][n-1-i] = old[i][j] 填值——思路正确,但题目要求原地,额外 O(n²) 空间会被判不符合。
2. 重复在哪里?若逐元素搬到临时变量再写回,本质上仍需要辅助存储;要把「顺时针 90°」拆成可在原数组上完成的原子操作。
3. 关键观察:顺时针 90° = 先转置(沿主对角线交换)再对每一行左右翻转。手画 3×3 例子可验证:转置后 [[1,4,7],[2,5,8],[3,6,9]],逐行翻转即得目标。
4. 坐标规律:原位置 (i,j) 顺时针 90° 后到 (j, n-1-i);转置把 (i,j)→(j,i),行翻转把 (j,i)→(j, n-1-i),两步合成即目标映射。
5. 另一种等价写法是按「同心层」四元组循环交换(每次转 4 个角),但转置+翻转代码更短、不易写错下标;n ≤ 20,O(n²) 完全够用。
变量语义(先读这三句再编码)
| 变量 | 类型 | 语义(三句法) |
|---|---|---|
matrix | list<list<int>> | 定义:n×n 方阵,既是输入也是最终输出维护:分两步原地变换——先沿主对角线转置,再对每一行左右翻转 更新:转置交换 matrix[i][j] 与 matrix[j][i];翻转交换行内 matrix[i][left] 与 matrix[i][right] |
n | int | 定义:矩阵边长,n = len(matrix)维护:转置时 i 取 0..n-1,j 取 i+1..n-1,避免同一对元素交换两次更新:全程不变,控制两层循环边界 |
i, j | int | 定义:转置阶段的双重下标,遍历上三角区域 维护:每对 (i,j) 满足 j > i,交换 matrix[i][j] 与 matrix[j][i]更新:双重循环递增;转置完成后进入逐行翻转阶段 |
left, right | int | 定义:翻转第 i 行时的双指针,分别指向行首与行尾维护: left < right 时交换 matrix[i][left] 与 matrix[i][right],然后 left++、right--更新:相遇时当前行翻转完成,换下一行 |
落码步骤
1. 取 n = len(matrix)
2. 转置:双重循环 for i in range(n): for j in range(i+1, n): 交换 matrix[i][j] 与 matrix[j][i]
3. 逐行翻转:对每行 i,令 left=0, right=n-1,当 left < right 时交换两端元素并收缩指针
4. 两步完成后 matrix 即为顺时针 90° 结果,无需返回值(原地修改)
代码实现
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
# 1. 沿主对角线转置
for i in range(n):
for j in range(i + 1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
# 2. 每一行左右翻转
for i in range(n):
left, right = 0, n - 1
while left < right:
matrix[i][left], matrix[i][right] = matrix[i][right], matrix[i][left]
left += 1
right -= 1
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// 1. 沿主对角线转置
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
swap(matrix[i][j], matrix[j][i]);
}
}
// 2. 每一行左右翻转
for (int i = 0; i < n; i++) {
int left = 0, right = n - 1;
while (left < right) {
swap(matrix[i][left], matrix[i][right]);
left++;
right--;
}
}
}
};
// 时间 O(n²),空间 O(1)
复杂度分析
O(n²)
O(1)(原地修改,不计输入)
常见坑
转置时 j 必须从 i+1 开始,不能从 0 开始——否则同一对元素会被交换两次,等于没转置。
逆时针 90° 是「转置 + 逐列翻转」或「先逐行翻转再转置」,与顺时针步骤不同;混用会得到错误结果。
题目要求原地修改、无返回值;新建矩阵再赋值虽能 AC 部分测试,但不符合题意且浪费空间。
必测边界 Case
matrix = [[1]] → [[1]](转置与翻转均为空操作)
matrix = [[1,2],[3,4]] → [[3,1],[4,2]]
matrix = [[-1,2],[-3,4]] → [[-3,-1],[4,2]](符号不影响交换逻辑)
matrix = [[1,2,3],[4,5,6],[7,8,9]] → [[7,4,1],[8,5,2],[9,6,3]](中心元素 5 转置后仍在中心)
见示例 2(无单独中心格,全靠成对交换完成)