题目:给定一个 n × n 的二维矩阵 matrix,将其顺时针旋转 90 度。要求原地旋转,不使用额外空间。
这题有个非常巧妙的技巧:先转置,再翻转每一行。我们来一步步拆解。
1. 图形化理解
先看个例子,假设矩阵是:
1 2 3
4 5 6
7 8 9
顺时针旋转 90 度后应该是:
7 4 1
8 5 2
9 6 3
第一步:转置(行列互换)
转置后矩阵变成:
1 4 7
2 5 8
3 6 9
关键点:转置会让 matrix[i][j] 和 matrix[j][i] 交换位置。注意内层循环 j < i,这样每个元素只交换一次,不会换回来。
第二步:翻转每一行
把转置后的每一行左右镜像:
7 4 1 ← 翻转第0行
8 5 2 ← 翻转第1行
9 6 3 ← 翻转第2行
关键点:j < m / 2 确保每行只翻转一半,否则又翻回去了。
2. 为什么这样有效?
从坐标变换的角度看:
- 顺时针旋转 90 度:
matrix[i][j]→matrix[j][n-1-i] - 转置操作:
matrix[i][j]→matrix[j][i] - 行翻转:
matrix[j][i]→matrix[j][n-1-i]
完美匹配! 先转置再翻转,等价于直接旋转。
3. 代码分析
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length; // 对于方阵,m == n
// 第一步:转置
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) { // 注意是 j < i,不是 j < n
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 第二步:翻转每一行
for(int i = 0; i < n; i++) {
for(int j = 0; j < m / 2; j++) { // 只需翻转一半
int temp = matrix[i][j];
matrix[i][j] = matrix[i][m - j - 1];
matrix[i][m - j - 1] = temp;
}
}
}
}
易错点提醒:
- 转置时内层循环必须是
j < i,否则会交换两次等于没换 - 行翻转时
j < m / 2,确保只交换到中间位置
4. 复杂度
- 时间复杂度:O(n²),遍历了矩阵两次
- 空间复杂度:O(1),只用了常数个临时变量