跳到正文
第 48 题中等

旋转图像

Rotate Image

把 n × n 矩阵原地顺时针旋转 90°,不能另开一个矩阵复制。

在力扣中练习

题目描述

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

 

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

 

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000

 

解题思路

主解法

转置 + 逐行翻转

先把行列互换,再把每行倒过来

顺时针 90° 后,原来第 c 列会变成第 c 行,而且方向相反。直接按这个关系搬格子会覆盖还没读的值;拆成两步就不会互相踩踏。

第一步转置:只遍历主对角线右上方的 (i,j),与 (j,i) 交换。每个无序点对只处理一次,主对角线不动。

分步图解

交换 (0,1) 与 (1,0):2 和 5 互换。

只处理 j>i 的上三角,每个无序点对只交换一次。

i
0
j
1
转置:沿主对角线交换 (i,j) 与 (j,i)
0
1
2
3
0
7
5
15
4
1
2
12
9
1
2
14
6
3
10
3
8
13
11
16
蓝色是一对正在交换的格子;(r,c) 转置后到 (c,r)。
访问顺序
转置 i<j每行 reverse
1 / 3
上三角的每一对格子互换,主对角线保持不动。

第二步逐行翻转:把每一行左右对调。两步复合,位置 (r,c) 最终到 (c,n-1-r),正是顺时针 90°。

分步图解

第 0 行 7 5 14 8 → 8 14 5 7。

逐行翻转:第 0 行左右对调
0
1
2
3
0
8
14
5
7
1
2
12
6
13
2
15
9
3
11
3
4
1
10
16
蓝色是一对正在交换的格子;(r,c) 转置后到 (c,r)。
访问顺序
转置 i<j每行 reverse
1 / 3
转置后每行内部再对调,第一列因此变成翻转后的最后一列。

自拟 4×4 矩阵的值两两不同,任何一次搬错都能从画面上看出来。原地操作只用到几个临时变量,额外空间是 O(1)。

时间 O(n²)空间 O(1)

易错点

  • 两层循环写成 j 从 0 开始:每对格子会被换回去,等于没转置。
  • 先逐行翻转再转置得到的是逆时针 90°,方向反了。
  • 转置时只处理 j > i;把主对角线也交换虽然无害,但会多做一半无效操作。
对照解法

四角轮换 · 逐层原地

把四个角看成一组,循环赋值一次转完一层

同样 O(1) 额外空间,但一次要同时维护四个位置;下标容易写错,适合作为原地操作的进阶对照。

每一层可以看成四个等长的边。位置 (layer,j) 旋转后依次对应右边、下边、左边的三个位置,四次赋值正好闭合,不需要转置。

从左上角开始,先把 matrix[layer][j] 存进临时变量,再按逆时针方向把另外三个位置搬过来,最后把临时变量放到右边。循环只走到 last - 1,四个角由同一层的不同轮次覆盖,不能重复处理。

这种写法少一次全矩阵遍历,但四个下标互相牵扯;面试里写出转置版更稳,四角版更适合检查是否真正理解了下标映射。

  1. 1layer 从 0 到 n/2-1,圈定当前层。
  2. 2j 从 layer 走到 last-1,处理这一层的每条边。
  3. 3按上 → 左 → 下 → 右的顺序搬四个位置。
  4. 4临时变量补到右上角,进入下一组。
时间 O(n²)空间 O(1)

易错点

  • j 走到 last:四个角会被重复处理,最后一组互相覆盖。
  • 四行赋值的顺序写反会得到逆时针旋转。
  • offset 忘记减 layer:内层的下标会整体偏移。

代码与演示

主解法配有图解;对照解法用于比较思路、复杂度或实现方式。

演示输入matrix = [[7,2,15,4],[5,12,9,1],[14,6,3,10],[8,13,11,16]]

先转置,再把每一行左右翻转;两步合起来正好是顺时针 90°。

转置:沿主对角线交换 (i,j) 与 (j,i)
0
1
2
3
0
7
2
15
4
1
5
12
9
1
2
14
6
3
10
3
8
13
11
16
蓝色是一对正在交换的格子;(r,c) 转置后到 (c,r)。
访问顺序
转置 i<j每行 reverse
1 / 6
查看 C++ 代码

延伸阅读

  • 矩阵旋转、转置、镜像都可以拆成两次简单的下标变换,先想清楚复合后的映射再写代码。
  • 如果题目允许额外空间,直接按 (r,c) → (c,n-1-r) 写入新矩阵最不容易错。
  • 同类题:螺旋矩阵按边界读取,旋转图像按边界写入,关注点都是“一圈一圈”处理。