LeetCode 48 & 1886.矩阵旋转与判断
题目概览
[LeetCode 48] 旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像,请你将图像顺时针旋转 90 度,必须原地旋转。
[LeetCode 1886] 判断矩阵经轮转后是否一致
给定两个 n × n 的矩阵 mat 和 target,判断 mat 能否通过若干次顺时针旋转 90 度 (0 到 3 次)变成 target。
解法思路
一、LeetCode 48:原地旋转矩阵
核心思想
顺时针旋转 90 度 = 转置矩阵 + 每行反转
数学原理
原矩阵元素 (i, j) 旋转后的新位置是 (j, n-1-i),通过两步操作实现:
- 转置 :
(i, j) → (j, i) - 行反转 :
(j, i) → (j, n-1-i)
代码实现
cpp
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// 第一步:转置矩阵(沿主对角线翻转)
for(int i = 0; i < n; i++)
for(int j = 0; j < i; j++)
swap(matrix[i][j], matrix[j][i]);
// 第二步:每行反转
for(auto& row : matrix)
ranges::reverse(row); // C++20 语法,等价于 reverse(row.begin(), row.end())
}
};
执行示例
原矩阵:
[1, 2, 3] [1, 4, 7] [7, 4, 1]
[4, 5, 6] -转置→ [2, 5, 8] -行反转→ [8, 5, 2]
[7, 8, 9] [3, 6, 9] [9, 6, 3]
复杂度分析
- 时间复杂度:O(n²),每个元素访问两次
- 空间复杂度:O(1),原地旋转
二、LeetCode 1886:复用旋转函数
核心思想
矩阵旋转 4 次(360°)回到原位,因此只需检查 0°、90°、180°、270° 四种状态。
算法步骤
- 复用上一题的
rotate函数 - 循环 4 次,每次先检查是否与
target相等 - 不等则旋转一次继续检查
- 4 次都不相等返回
false
代码实现
cpp
class Solution {
// 复用 LeetCode 48 的旋转函数
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for(int i = 0; i < n; i++)
for(int j = 0; j < i; j++)
swap(matrix[i][j], matrix[j][i]);
for(auto& row : matrix)
ranges::reverse(row);
}
public:
bool findRotation(vector<vector<int>>& mat, vector<vector<int>>& target) {
for(int i = 0; i < 4; i++) { // 最多旋转 4 次
if(mat == target) // 检查当前状态
return true;
rotate(mat); // 顺时针旋转一次
}
return false; // 4 种状态都不匹配
}
};
执行流程
| 循环次数 | 操作 | 检查的角度 |
|---|---|---|
| i = 0 | 先检查后旋转 | 0°(原始状态) |
| i = 1 | 先检查后旋转 | 90° |
| i = 2 | 先检查后旋转 | 180° |
| i = 3 | 先检查后旋转 | 270° |
| 循环结束 | - | 已检查所有可能 |
为什么循环 4 次?
- 旋转 4 次(360°)回到原始状态
- 4 次检查覆盖所有不同朝向
- 注意:先检查再旋转,这样最后一次循环检查完 270° 后不会多转一次
复杂度分析
- 时间复杂度:O(n²),每次旋转 O(n²),最多 4 次(常数因子忽略)
- 空间复杂度:O(1),原地操作
总结对比
| 题目 | 核心技巧 | 关键点 |
|---|---|---|
| 48. 旋转图像 | 转置 + 行反转 | 原地操作,数学变换 |
| 1886. 判断矩阵轮转 | 复用旋转函数 | 循环 4 次,先检查后旋转 |
代码复用优势
- 避免重复实现旋转逻辑
- 保持代码简洁易维护
- 体现模块化设计思想
常见误区
- 旋转方向错误:顺时针是转置+行反转,逆时针是转置+列反转
- 循环次数错误:旋转 4 次回到原位,但只需检查 4 次(含 0 次)
- 检查顺序错误:应先检查当前状态再旋转,确保检查到原始状态
完整测试用例
cpp
// 示例 1
mat = [[1,2,3],[4,5,6],[7,8,9]]
target = [[7,4,1],[8,5,2],[9,6,3]]
输出:true(旋转 90°)
// 示例 2
mat = [[1,1],[2,2]]
target = [[1,1],[2,2]]
输出:true(旋转 0°)
// 示例 3
mat = [[1,1],[2,2]]
target = [[2,1],[2,1]]
输出:false
💡 小技巧:遇到矩阵旋转问题,优先考虑「转置 + 反转」的组合,避免复杂的坐标映射计算。