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 度可以分解为两步:

  1. 转置矩阵(行列互换)
  2. 水平翻转每一行

为什么这样可行?

我们来看一个 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)(原地修改)。

通常面试中掌握方法一即可快速解题,理解方法二有助于加深对矩阵操作的认识。

好的,我们接下来讲解 LeetCode 第 48 题:“旋转图像” 。 题目描述 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像 顺时针旋转 90 度 。 要求: 必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。 不要 使用另一个矩阵来旋转图像。 示例 1: 示例 2: 解题思路 为了在原地旋转矩阵,我们可以通过 两次操作 来实现顺时针 90 度的效果。 方法一:数学推导(转置 + 翻转) 顺时针旋转 90 度可以分解为两步: 转置矩阵 (行列互换) 水平翻转每一行 为什么这样可行? 我们来看一个 3x3 矩阵的例子: 原始矩阵: 第一步:转置(行列互换) 第 i 行变成第 i 列 第二步:水平翻转每一行 每行元素左右交换 这正是顺时针旋转 90 度的结果。 详细步骤 步骤 1:转置矩阵 遍历矩阵的上三角(不包括对角线或包括对角线都可以,但要注意不要重复交换) 对于每个元素 matrix[i][j] ,交换 matrix[i][j] 和 matrix[j][i] 注意:只需要遍历 i < j 的部分,避免重复交换 步骤 2:水平翻转每一行 对于每一行,使用双指针法,将首尾对应的元素交换 指针从两端向中间移动,直到相遇 代码实现(思路对应) 方法二:逐层旋转(更直观的模拟) 对于 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 保存一个位置的值,然后逆序赋值,完成四个位置的交换。 方法二代码实现 总结 方法一(转置+翻转) 思路简单,代码简洁,容易记忆。 方法二(逐层旋转) 更符合旋转的直观过程,但索引计算稍复杂。 两种方法的时间复杂度都是 O(n²) ,空间复杂度都是 O(1) (原地修改)。 通常面试中掌握方法一即可快速解题,理解方法二有助于加深对矩阵操作的认识。