LeetCode 48. 旋转图像
题目描述
✅ 48. 旋转图像


题意分析
给定
n × n的正方形矩阵,要求把整个图像顺时针旋转90°,直接修改原矩阵,不返回一个新矩阵,也不能另建同等大小的矩阵保存结果。旋转改变的是元素位置,元素值本身不变。原来的第一行会成为旋转后的最后一列;如果逐格直接写入目标位置,就可能覆盖尚未搬走的旧值,因此需要安排不会丢失数据的原地交换。
解法:转置矩阵后反转每一行
核心思路
[!blue]
先明确目标坐标。使用从
0开始的下标,原位置(i, j)顺时针旋转后位于(j, n - 1 - i):原列下标变成新行下标,原行越靠上,新列就越靠右。这个映射可以拆成两个容易原地完成的步骤。第一步沿主对角线转置,把
(i, j)与(j, i)交换,元素从(i, j)到达(j, i)。第二步反转每一行,把列下标i变成n - 1 - i,于是元素最终到达(j, n - 1 - i),与旋转要求完全一致。转置时只遍历主对角线一侧,也就是
j > i的上三角。每对对称位置只交换一次;若两侧都处理,同一对元素会被交换两次而回到原位。主对角线上的元素转置前后位置不变,无需交换。行反转使用左右指针向中间靠拢,每次交换一对首尾元素。两步都只是交换,不会丢失尚未处理的值,也不需要额外矩阵;奇数长度行的中间元素无需交换。
解题步骤
- 读取矩阵边长
n。- 对每一行
i,从j = i + 1开始遍历上三角,将matrix[i][j]与matrix[j][i]交换,完成转置。- 对转置后的每一行,设置左右指针,从两端向中间交换元素,完成行反转。
- 两步结束后,原矩阵已经变成顺时针旋转后的结果,无需创建或返回新矩阵。
代码实现
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n; i++) {
// 只交换对角线一侧,每对镜像位置恰好处理一次。
for (int j = i + 1; j < n; j++) {
int value = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = value;
}
}
// 转置后再反转每行,组合为顺时针九十度旋转。
for (int[] row : matrix) {
reverse(row);
}
}
private void reverse(int[] row) {
int left = 0;
int right = row.length - 1;
while (left < right) {
int value = row[left];
row[left] = row[right];
row[right] = value;
left++;
right--;
}
}
}
func rotate(matrix [][]int) {
n := len(matrix)
for i := 0; i < n; i++ {
// 只交换对角线一侧,每对镜像位置恰好处理一次。
for j := i + 1; j < n; j++ {
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
}
}
// 转置后再反转每行,组合为顺时针九十度旋转。
for i := range matrix {
reverseInts(matrix[i])
}
}
func reverseInts(nums []int) {
left, right := 0, len(nums)-1
for left < right {
nums[left], nums[right] = nums[right], nums[left]
left++
right--
}
}
复杂度分析
- 时间复杂度:$O(n^2)$。转置与逐行反转处理的元素总数都与 $n^2$ 同阶。
- 空间复杂度:$O(1)$。只使用临时变量和下标,直接修改原矩阵。
关键点总结
[!green]
- 目标映射是
(i, j) → (j, n - 1 - i),用它核对变换顺序就不会混淆方向。- 主对角线转置负责交换行列下标,逐行反转负责翻转新列的位置。
- 每一对元素只交换一次,保证原地操作既不覆盖旧值,也不把变换撤销。
易错点总结
[!yellow]
- 转置时扫描完整矩阵,会把同一对位置交换两次;内层应从
i + 1开始。- 转置后反转每一列,得到的是逆时针旋转,和要求的方向相反。
- 直接写
matrix[j][n - 1 - i] = matrix[i][j],会覆盖目标位置原有且尚未移动的值。- 新建矩阵后仅令局部变量
matrix = rotated,不会替换调用方原矩阵的内容,也不符合原地修改要求。- 该转置交换依赖行列数相等,本题保证方阵,不能把相同下标循环直接套到非方阵。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 867. 转置矩阵 | 简单 | 顺时针旋转可拆成矩阵转置再逐行反转,原题只做转置。 |
| 344. 反转字符串 | 简单 | 完成矩阵转置后,每一行都直接使用左右双指针交换实现反转;该题就是这一行内反转步骤的独立练习。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!