LeetCode 第 48 题:“旋转图像”
字数 1179 2025-10-26 01:26:05
好的,我们接下来讲解 LeetCode 第 48 题:“旋转图像”。
题目描述
给定一个 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]]
解题思路
为了在原地旋转矩阵,我们可以通过 两次操作 来实现顺时针 90 度的效果。
方法一:数学推导(转置 + 翻转)
顺时针旋转 90 度可以分解为两步:
- 转置矩阵(行列互换)
- 水平翻转每一行
为什么这样可行?
我们来看一个 3x3 矩阵的例子:
原始矩阵:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
第一步:转置(行列互换)
- 第 i 行变成第 i 列
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
第二步:水平翻转每一行
- 每行元素左右交换
[7, 4, 1]
[8, 5, 2]
[9, 6, 3]
这正是顺时针旋转 90 度的结果。
详细步骤
步骤 1:转置矩阵
- 遍历矩阵的上三角(不包括对角线或包括对角线都可以,但要注意不要重复交换)
- 对于每个元素
matrix[i][j],交换matrix[i][j]和matrix[j][i] - 注意:只需要遍历
i < j的部分,避免重复交换
步骤 2:水平翻转每一行
- 对于每一行,使用双指针法,将首尾对应的元素交换
- 指针从两端向中间移动,直到相遇
代码实现(思路对应)
def rotate(matrix):
n = len(matrix)
# 步骤 1:转置矩阵
for i in range(n):
for j in range(i + 1, n): # 注意 j 从 i+1 开始,避免重复交换
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
方法二:逐层旋转(更直观的模拟)
对于 n x n 矩阵,可以看作由外到内的一圈圈“层”组成。
每一层进行旋转:将每条边上的元素依次移动。
具体操作(对于一层):
- 将上边的元素移到右边
- 将右边的元素移到下边
- 将下边的元素移到左边
- 将左边的元素移到上边
如何确定层的范围?
- 层数从 0 到
n//2(因为 n 为奇数时最中间一个元素不需要旋转)
对于第 layer 层:
- 该层有
n - 2 * layer的长度 - 需要旋转的元素索引范围是
[layer, n - 1 - layer]
旋转四个位置的元素:
- 上边
(layer, i)→ 右边(i, n-1-layer) - 右边
(i, n-1-layer)→ 下边(n-1-layer, n-1-i) - 下边
(n-1-layer, n-1-i)→ 左边(n-1-i, layer) - 左边
(n-1-i, layer)→ 上边(layer, i)
用临时变量 temp 保存一个位置的值,然后逆序赋值,完成四个位置的交换。
方法二代码实现
def rotate(matrix):
n = len(matrix)
for layer in range(n // 2):
first, last = layer, n - 1 - layer
for i in range(first, last):
offset = i - first
# 保存上边
top = matrix[first][i]
# 左到上
matrix[first][i] = matrix[last - offset][first]
# 下到左
matrix[last - offset][first] = matrix[last][last - offset]
# 右到下
matrix[last][last - offset] = matrix[i][last]
# 上到右
matrix[i][last] = top
总结
- 方法一(转置+翻转) 思路简单,代码简洁,容易记忆。
- 方法二(逐层旋转) 更符合旋转的直观过程,但索引计算稍复杂。
- 两种方法的时间复杂度都是 O(n²),空间复杂度都是 O(1)(原地修改)。
通常面试中掌握方法一即可快速解题,理解方法二有助于加深对矩阵操作的认识。