【LeetCode 每日一题】1886. 判断矩阵经轮转后是否一致
Problem: 1886. 判断矩阵经轮转后是否一致
文章目录
- 整体思路
- 完整代码
- 时空复杂度
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
整体思路
这段代码的目的是判断一个 n x n 的二维矩阵 mat
是否可以通过顺时针旋转90度若干次(0次、1次、2次或3次)后,与另一个 n x n 的矩阵 target
相等。
该算法采用了一种非常直观的 模拟旋转与比较 的策略。它不试图通过数学变换直接判断,而是真实地模拟每一次旋转,并在每次旋转后进行一次完整的比较。
-
核心思想:枚举所有旋转状态
- 一个矩阵顺时针旋转90度,总共有 4 种可能的状态:
- 旋转 0 次(原始状态)
- 旋转 1 次 (90度)
- 旋转 2 次 (180度)
- 旋转 3 次 (270度)
- 旋转 4 次 (360度) 会回到原始状态,无需再检查。
- 算法的思路就是,逐一生成这 4 种状态,并与
target
矩阵进行比较。只要有一次比较结果为true
,就可以立即确定mat
可以通过旋转得到target
。
- 一个矩阵顺时针旋转90度,总共有 4 种可能的状态:
-
findRotation
主函数逻辑for (int i = 0; i <= 3; i++)
: 这个循环控制了检查的次数,总共 4 次,对应 0, 90, 180, 270 度的旋转。if (Arrays.deepEquals(mat, target))
: 在循环的开始,首先检查当前状态的mat
是否与target
相等。Arrays.deepEquals
是一个专门用于比较多维数组内容的标准库函数。- 第一次循环 (i=0),检查的是原始
mat
(旋转0度)。 - 如果相等,立即
return true
。
- 第一次循环 (i=0),检查的是原始
rotate(mat);
: 如果当前状态不匹配,就调用rotate
辅助函数,对mat
进行一次原地顺时针90度旋转。这样,在下一次循环开始时,mat
就变成了下一个旋转状态。- 如果循环 4 次结束后,都没有找到匹配的状态,说明
mat
无论如何旋转都无法等于target
,最终return false
。
-
rotate
辅助函数逻辑- 这个函数实现了 n x n 矩阵的原地顺时针旋转90度。这是一个经典的矩阵操作,通常分两步完成:
a. 沿主对角线翻转(转置):for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) ... }
- 这个嵌套循环遍历矩阵的下三角部分,将
mat[i][j]
与mat[j][i]
进行交换。完成后,整个矩阵就完成了转置操作。
b. 沿垂直中轴线翻转(水平翻转): for (int i = 0; i < n / 2; i++) { for (int j = 0; j < n; j++) ... }
- 这个循环遍历矩阵的左半部分(按列),将第
i
列与第n-1-i
列的元素进行交换。完成后,就实现了水平翻转。
- 这个函数实现了 n x n 矩阵的原地顺时针旋转90度。这是一个经典的矩阵操作,通常分两步完成:
完整代码
import java.util.Arrays;class Solution {/*** 判断矩阵 mat 是否可以通过顺时针旋转90度若干次后与 target 相等。* @param mat 输入的 n x n 矩阵* @param target 目标 n x n 矩阵* @return 如果可以,返回 true;否则返回 false。*/public boolean findRotation(int[][] mat, int[][] target) {// 循环 4 次,分别检查旋转 0, 90, 180, 270 度的状态for (int i = 0; i <= 3; i++) {// 检查当前状态的 mat 是否与 target 相等if (Arrays.deepEquals(mat, target)) {return true;}// 如果不相等,则将 mat 原地旋转90度,为下一次检查做准备rotate(mat);}// 如果 4 种状态都不匹配,则返回 falsereturn false;}/*** 辅助函数:将 n x n 矩阵 mat 原地顺时针旋转90度。* 实现方式:先沿主对角线翻转(转置),再沿水平中轴线翻转(垂直翻转)。* @param mat 要旋转的 n x n 矩阵*/public void rotate(int[][] mat) {int n = mat.length;// 步骤 1: 沿主对角线翻转 (矩阵转置)// e.g., mat[i][j] <-> mat[j][i]for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++) {int temp = mat[i][j];mat[i][j] = mat[j][i];mat[j][i] = temp;}}// 步骤 2: 沿水平中轴线翻转 (垂直翻转)// e.g., 将第 i 行与第 n-1-i 行交换for (int i = 0; i < n / 2; i++) {for (int j = 0; j < n; j++) {int temp = mat[i][j];mat[i][j] = mat[n - 1 - i][j];mat[n - 1 - i][j] = temp;}}}
}
时空复杂度
- 设矩阵是
N x N
的。
时间复杂度:O(N^2)
findRotation
主函数:- 外层
for
循环执行固定 4 次。 Arrays.deepEquals(mat, target)
需要比较两个N x N
矩阵的所有元素,其时间复杂度为 O(N^2)。rotate(mat)
的时间复杂度(见下文分析)也是 O(N^2)。- 因此,
findRotation
的总时间复杂度是4 * (O(N^2) + O(N^2))
。
- 外层
rotate
辅助函数:- 转置:嵌套循环的总迭代次数是
1 + 2 + ... + (N-1) = N*(N-1)/2
,即 O(N^2)。 - 翻转:嵌套循环的总迭代次数是
N * (N/2)
,即 O(N^2)。 - 因此,
rotate
的时间复杂度是 O(N^2) + O(N^2) = O(N^2)。
- 转置:嵌套循环的总迭代次数是
综合分析:
总的时间复杂度是 4 * O(N^2)
,在 Big O 表示法中,常数因子被忽略。因此,最终的时间复杂度是 O(N^2)。
空间复杂度:O(1)
- 主要存储开销:
findRotation
方法只使用了i
这个循环变量。rotate
方法使用了n
,i
,j
,temp
等几个基本类型的变量。- 关键在于,所有的旋转操作都是原地 (in-place) 在
mat
数组上完成的,没有创建任何与矩阵大小N x N
成比例的新的数据结构。
综合分析:
算法所需的额外辅助空间是常数级别的。因此,其空间复杂度为 O(1)。