LeetCode 每日一题笔记
0. 前言
- 日期:2025.03.22
- 题目:1886.判断矩阵经轮转后是否一致
- 难度:简单
- 标签:数组 矩阵 旋转 模拟
1. 题目理解
问题描述 :
给你两个大小为 n x n 的二进制矩阵 mat 和 target 。现以 90 度顺时针轮转矩阵 mat 中的元素若干次,如果能够使 mat 与 target 一致,返回 true ;否则,返回 false 。
示例:
输入:mat = [[0,1],[1,0]], target = [[1,0],[0,1]]
输出:true
解释:
mat 顺时针轮转 90 度后:
原矩阵 [[0,1],[1,0]] → 旋转90度后 [[1,0],[0,1]],与 target 一致,因此返回 true。
补充说明:
- 正方形矩阵顺时针旋转90度最多旋转4次会回到原始状态;
- 需检查旋转0次(原矩阵)、90次、180次、270次后是否与target一致。
2. 解题思路
核心观察
- 正方形矩阵顺时针旋转90度的规律:先转置矩阵(行列互换),再反转每一行;
- 矩阵最多旋转4次就会回到初始状态,因此只需检查0/90/180/270度旋转后的结果;
- 若旋转4次后仍未匹配target,则返回false。
算法步骤
- 前置校验:检查mat和target的行列数是否一致,不一致直接返回false;
- 检查初始状态:若mat未旋转时已与target一致,直接返回true;
- 模拟旋转并校验 :
- 对mat执行90度顺时针旋转;
- 检查旋转后的矩阵是否与target一致,一致则返回true;
- 重复旋转和校验操作,直到完成3次旋转(覆盖90/180/270度);
- 最终判断:若4种旋转状态均不匹配,返回false。
3. 代码实现
java
class Solution {
public static boolean same(int[][] mat, int[][] target, int a, int b) {
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
if (mat[i][j] != target[i][j]) {
return false;
}
}
}
return true;
}
public static int[][] switchroom(int[][] mat) {
int n = mat.length;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int temp = mat[i][j];
mat[i][j] = mat[j][i];
mat[j][i] = temp;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n / 2; j++) {
int temp = mat[i][j];
mat[i][j] = mat[i][n - 1 - j];
mat[i][n - 1 - j] = temp;
}
}
return mat;
}
public boolean findRotation(int[][] mat, int[][] target) {
int a = mat.length;
int b = mat[0].length;
int c = target.length;
int d = target[0].length;
if (a != c || b != d) {
return false;
}
if (same(mat, target, a, b)) {
return true;
}
switchroom(mat);
if (same(mat, target, a, b)) {
return true;
}
switchroom(mat);
if (same(mat, target, a, b)) {
return true;
}
switchroom(mat);
if (same(mat, target, a, b)) {
return true;
}
return false;
}
}
4. 代码优化说明
优化点1:避免修改原矩阵(无副作用)
原代码直接修改输入的mat矩阵,可能对外部使用造成影响,优化为复制矩阵后旋转:
java
public boolean findRotation(int[][] mat, int[][] target) {
int n = mat.length;
// 复制原矩阵,避免修改输入
int[][] copy = new int[n][n];
for (int i = 0; i < n; i++) {
System.arraycopy(mat[i], 0, copy[i], 0, n);
}
// 检查4种旋转状态
for (int i = 0; i < 4; i++) {
if (same(copy, target, n, n)) {
return true;
}
copy = switchroom(copy);
}
return false;
}
优化点2:简化旋转逻辑(提取独立方法)
将旋转逻辑封装为更清晰的方法,提升可读性:
java
private int[][] rotate90(int[][] matrix) {
int n = matrix.length;
int[][] res = new int[n][n];
// 直接计算旋转后位置,无需转置+反转(更直观)
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
res[j][n - 1 - i] = matrix[i][j];
}
}
return res;
}
优化点3:提前终止循环
原代码重复调用switchroom和same,优化为循环遍历4次,匹配后立即返回:
java
public boolean findRotation(int[][] mat, int[][] target) {
int n = mat.length;
if (n != target.length || n != target[0].length) return false;
int[][] curr = mat;
for (int i = 0; i < 4; i++) {
if (same(curr, target, n, n)) return true;
curr = switchroom(curr);
}
return false;
}
5. 复杂度分析
-
时间复杂度:(O(n^2))
- 每次矩阵旋转的时间为 (O(n^2))(转置+反转每行);
- 每次矩阵比较的时间为 (O(n^2));
- 最多执行4次旋转+4次比较,总时间为 (4 \times (n^2 + n^2) = O(n^2))(常数系数可忽略)。
-
空间复杂度:
- 原代码:(O(1))(原地旋转,仅使用常量临时变量);
- 优化版(不修改原矩阵):(O(n^2))(存储矩阵副本)。
6. 总结
- 核心思路是模拟旋转 + 逐次校验:利用矩阵旋转规律模拟90度顺时针旋转,检查4种旋转状态是否匹配target;
- 关键技巧:正方形矩阵顺时针旋转90度可通过"转置+反转每行"实现,且最多旋转4次必回原状态;
- 优化方向:避免修改原矩阵提升代码鲁棒性,直接计算旋转后位置简化旋转逻辑。
关键点回顾
- 矩阵顺时针旋转90度的两种实现方式:转置+反转行,或直接计算位置
res[j][n-1-i] = matrix[i][j]; - 只需检查0/90/180/270度四种旋转状态,无需无限旋转;
- 原地旋转空间复杂度为 (O(1)),是该问题的最优空间方案。