力扣刷题#12:LeetCode48旋转图像_刷题笔记
题目描述
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
Step 1:先找直觉——旋转的本质是什么?
盯着一个元素看,顺时针转 90° 后它去了哪里?
以 3×3 矩阵为例:
1 2 3 7 4 1
4 5 6 → 8 5 2
7 8 9 9 6 3
找几个位置映射:
| 旧位置 (i, j) | 新位置 (?, ?) |
|---|---|
| (0, 0) | (0, 2) |
| (0, 1) | (1, 2) |
| (0, 2) | (2, 2) |
| (1, 0) | (0, 1) |
观察规律:
- 新位置的行号 = 旧位置的列号 →
j - 新位置的列号 =
n - 1 - i(从右边数第 i 个)
旋转公式:
(i, j) → (j, n - 1 - i)
Step 2:为什么「转置 + 反转每行」等于旋转?
光背公式不好理解,这里有一个直观的物理视角:
用透明纸来想象
假设矩阵打印在一张透明纸上。
第一步:沿主对角线(左上→右下)对折 → 转置
对折前: 对折后(转置):
1 2 3 1 4 7
4 5 6 → 2 5 8
7 8 9 3 6 9
对折这个动作,就是把「行坐标」和「列坐标」互换。公式:(i, j) → (j, i)
第二步:水平翻转(每行左右镜像)→ 反转每行
转置后: 水平翻转后:
1 4 7 7 4 1
2 5 8 → 8 5 2
3 6 9 9 6 3
公式:(j, i) → (j, n - 1 - i)
两步合并
(i, j) → 转置 → (j, i) → 反转 → (j, n - 1 - i) ← 旋转 90° 公式!
我踩过的坑
❌ vector 的 .length 不存在
int n = matrix[0].length; // ❌ 编译错误
int n = matrix.size(); // ✅ 用 .size()
length 是 Java 和 JavaScript 的用法,C++ 的 vector 只有 .size()。
最终 AC 代码
class Solution {
public:void rotate(vector<vector<int>>& matrix) {int n = matrix.size();// 第一步:转置(沿主对角线翻转)for (int i = 0; i < n; i++)for (int j = i; j < n; j++)swap(matrix[i][j], matrix[j][i]);// 第二步:每行反转(水平翻转)for (int i = 0; i < n; i++)reverse(matrix[i].begin(), matrix[i].end());}
};
| 复杂度 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n²) | 每个元素访问两次(转置 + 反转) |
| 空间复杂度 | O(1) | 原地修改,没有额外数组 |
这道题到底在考什么?
第一层:矩阵坐标变换(硬实力)
能不能把「旋转」这个直观动作翻译成数学公式。面试官想看到你推导公式的过程,而不是背答案。
第二层:原地操作意识(工程能力)
题目特意强调不要用另一个矩阵,这就是在考内存意识。两种写法的对比:
| 写法 | 空间 | 评价 |
|---|---|---|
| 新开一个 n×n 矩阵 | O(n²) | ❌ 没读懂题目要求 |
| 转置 + 每行反转 | O(1) | ✅ 合格的原地操作 |
第三层:问题分解能力(软实力)
旋转 = 转置 + 反转
能把一个复杂变换拆成两个简单操作的组合,才是面试官最想看到的能力。很多题目都可以用这种「分步拆解」的思路来解决。
拓展:如果逆时针旋转 90° 呢?
两步反过来:
先转置(和顺时针一样)
再垂直翻转(上下翻,不是左右翻)
// 逆时针旋转 90°
for (int i = 0; i < n; i++)for (int j = i; j < n; j++)swap(matrix[i][j], matrix[j][i]); // 先转置for (int i = 0; i < n / 2; i++)swap(matrix[i], matrix[n - 1 - i]); // 再上下翻转
记住:「对折(转置)+ 翻页(反转)= 旋转」,这个视角比死记公式有用得多。
本文档由 AI 辅助生成,作者提供问题,思路和代码,综合获得以上内容。
