本文最后更新于 2026-01-09,文章内容可能已经过时。

「旋转图像」是 LeetCode 中经典的中等难度题目,核心考察矩阵元素位置映射原地修改技巧。这道题的关键是在不使用额外矩阵的前提下,按顺时针 90 度旋转,同时准确处理元素的目标位置。

实际开发中,图像旋转、矩阵数据格式转换等场景都能用到它的思路。今天从暴力解法出发,一步步优化到最简洁的 O (1) 空间最优解,带你吃透矩阵旋转的核心逻辑~

📌 题目重述

给你一个 n x n 的二维矩阵 matrix,请顺时针旋转 90 度原地修改(不能创建额外二维矩阵,允许常数级额外空间)。

🚶 阶梯思路拆解

第一步:暴力思路(额外矩阵存储)🥾

最直观的想法是利用位置映射规律,用新矩阵存储旋转后的元素,再复制回原矩阵。逻辑简单但需额外空间,适合理解映射关系。

💡 核心逻辑

  1. 核心映射规律:原矩阵 (i,j) 位置的元素,旋转后会移动到 (j, n-1-i) 位置

  2. 创建新矩阵 newMatrix,按映射规律复制原矩阵元素;

  3. 将新矩阵元素复制回原矩阵,实现伪原地修改。

📊 图文演示(3x3 矩阵)

(如图所示)映射过程:

  • (0,0)=1 → (0,2);(0,1)=2 → (1,2);(0,2)=3 → (2,2);

  • (1,0)=4 → (0,1);(1,1)=5 → (1,1);(1,2)=6 → (2,1);

  • (2,0)=7 → (0,0);(2,1)=8 → (1,0);(2,2)=9 → (2,0);

  • 新矩阵构建后复制回原矩阵,完成旋转。

✅ 代码实现(Java)

public class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int[][] newMatrix = new int[n][n];

        // 按映射规律复制元素
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                newMatrix[j][n - 1 - i] = matrix[i][j];
            }
        }

        // 复制回原矩阵
        for (int i = 0; i < n; i++) {
            System.arraycopy(newMatrix[i], 0, matrix[i], 0, n);
        }
    }
}

⚙️ 复杂度分析

复杂度类型

计算结果

说明

时间复杂度

O(n²)

两次遍历 n×n 矩阵,整体线性时间

空间复杂度

O(n²)

额外矩阵占用 O (n²) 空间,不符合原地要求

🚫 遇到的问题

额外矩阵占用大量内存,当 n=10³ 时,需占用 10⁶ 个元素空间。核心优化方向是:找到原地交换元素的方法,无需额外矩阵

第二步:最优解法(转置 + 水平翻转)🔑

这是最简洁高效的原地解法!利用矩阵的转置和行翻转组合,两步即可实现顺时针 90 度旋转,逻辑直观且空间复杂度 O (1)。

先验证核心原理

以 3x3 矩阵为例:

  1. 原矩阵 → 转置(行变列)→ 水平翻转每行 → 旋转结果;

    • 原矩阵: [[1,2,3],[4,5,6],[7,8,9]];

    • 转置后: [[1,4,7],[2,5,8],[3,6,9]];

    • 水平翻转后: [[7,4,1],[8,5,2],[9,6,3]](符合预期)。

原理推导

  • 转置:原 (i,j) → 转置后 (j,i);

  • 水平翻转:转置后 (i,j) → 翻转后 (i, n-1-j);

  • 组合效果:原 (i,j) → 最终 (j, n-1-i),与暴力解法的映射规律完全一致!

💡 核心逻辑

  1. 矩阵转置:遍历上三角区域( i < j),交换 (i,j) 和 (j,i)(避免重复交换);

  2. 水平翻转每行:遍历每行的前半部分,交换 (i,j) 和 (i, n-1-j);

  3. 两步操作完成旋转,全程原地修改。

📊 图文演示(3x3 矩阵)

矩阵变换可视化

✅ 代码实现(Java,最简洁)

public class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;

        // 步骤1:转置矩阵(行变列)
        for (int i = 0; i < n; i++) {
            // 只遍历上三角(i < j),避免重复交换
            for (int j = i + 1; j < n; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }

        // 步骤2:水平翻转每行
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n / 2; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][n - 1 - j];
                matrix[i][n - 1 - j] = temp;
            }
        }
    }
}

⚙️ 复杂度分析

复杂度类型

计算结果

说明

时间复杂度

O(n²)

转置和翻转各遍历矩阵一次,总操作数 O (n²)

空间复杂度

O(1)

仅使用常数个临时变量,完全原地修改

✨ 核心优势

  1. 逻辑简洁:两步操作即可完成,无需记忆复杂的位置映射;

  2. 效率拉满:时间 O (n²)、空间 O (1),满足所有题目要求;

  3. 易于实现:代码行数少,无复杂循环嵌套,面试中极易手写。

第三步:边界情况与易错点

常见边界场景

  • 1x1 矩阵( [[5]]):转置和翻转后不变,正确;

  • 2x2 矩阵( [[1,2],[3,4]]):转置后 [[1,3],[2,4]],翻转后 [[3,1],[4,2]],正确;

  • 奇数阶矩阵(如 5x5):中心元素转置和翻转后位置不变,正确。

易错点提醒

  • 转置时遍历全部元素:导致 (i,j) 和 (j,i) 重复交换,矩阵变回原样;

  • 翻转时遍历整行:重复交换元素,行翻转无效;

  • 忽略矩阵是正方形:本题仅适用于 n×n 矩阵,无需处理非正方形场景(题目限定输入为 n×n)。

📝 总结

「旋转图像」的解题核心是矩阵操作的组合技巧,从暴力到最优的思路递进清晰:

  1. 暴力解法:利用位置映射,额外矩阵存储,空间 O (n²);

  2. 最优解法:转置 + 水平翻转,原地修改,空间 O (1),逻辑简洁高效。

关键技巧

  • 核心组合:顺时针 90 度旋转 = 转置矩阵 + 水平翻转每行;

  • 转置技巧:仅遍历上三角区域( i < j),避免重复交换;

  • 翻转技巧:仅遍历每行前半部分( j < n/2),高效完成对称翻转。

同类题扩展建议

掌握本题思路后,可尝试这些进阶题目:

  1. LeetCode 189. 旋转数组:一维数组的旋转,思路与矩阵翻转有共通之处;

  2. LeetCode 54. 螺旋矩阵:矩阵遍历的边界控制,与矩阵操作逻辑互补;

  3. LeetCode 59. 螺旋矩阵 II:螺旋矩阵的反向构造,锻炼矩阵位置映射能力;

  4. LeetCode 498. 对角线遍历:矩阵对角线遍历,同样考察元素位置规律。

这类矩阵操作题的核心是找到元素位置的变换规律,通过组合简单的基础操作(转置、翻转、交换),就能高效解决复杂问题~