做网站需要的注意事项,手游官网首页,兰州模板型网站建设,织梦网站统计840. 矩阵中的幻方
问题描述
33 幻方 是一个填充了从 1 到 9 的不同数字的 33 网格#xff0c;其中每行、每列以及两条对角线的和都等于 15。
给定一个 row x col 的整数矩阵 grid#xff0c;返回矩阵中 33 幻方子矩阵 的数量。
注意#xff1a;
幻方必须包含数字 1-9#…840. 矩阵中的幻方问题描述3×3 幻方是一个填充了从 1 到 9 的不同数字的 3×3 网格其中每行、每列以及两条对角线的和都等于15。给定一个row x col的整数矩阵grid返回矩阵中3×3 幻方子矩阵的数量。注意幻方必须包含数字 1-9每个数字恰好出现一次幻方的中心必须是 5这是一个重要的数学性质示例输入:grid[[4,3,8,4],[9,5,1,9],[2,7,6,2]]输出:14 3 8 4 9 5 1 9 2 7 6 2只有左上角的 3×3 子矩阵是幻方4 3 8 9 5 1 2 7 6算法思路核心3×3 幻方必须包含数字 1-9 各一次幻方的中心必须是 5所有行、列、对角线的和必须等于 15只有8 种可能的 3×3 幻方通过旋转和镜像得到方法方法一遍历所有可能的 3×3 子矩阵逐一验证方法二利用中心必须为 5只检查中心为 5 的位置方法三预计算所有8种幻方直接匹配代码实现方法一完整验证classSolution{/** * 计算矩阵中3x3幻方的数量 * 3x3幻方包含1-9各一次每行/列/对角线和为15中心必须为5 * * param grid 输入矩阵 * return 幻方数量 */publicintnumMagicSquaresInside(int[][]grid){introwsgrid.length;intcolsgrid[0].length;intcount0;// 遍历所有可能的3x3子矩阵的左上角// 行范围0 到 rows-3列范围0 到 cols-3for(inti0;irows-3;i){for(intj0;jcols-3;j){// 幻方中心必须是5if(grid[i1][j1]5){if(isMagicSquare(grid,i,j)){count;}}}}returncount;}/** * 验证以(i,j)为左上角的3x3子矩阵是否为幻方 * * param grid 原矩阵 * param i 子矩阵左上角行索引 * param j 子矩阵左上角列索引 * return 是否为幻方 */privatebooleanisMagicSquare(int[][]grid,inti,intj){// 检查是否包含1-9各一次boolean[]seennewboolean[10];// 索引0-9使用1-9// 遍历3x3子矩阵的所有元素for(intr0;r3;r){for(intc0;c3;c){intnumgrid[ir][jc];// 数字必须在1-9范围内if(num1||num9){returnfalse;}// 检查是否重复if(seen[num]){returnfalse;}seen[num]true;}}// 验证所有行的和为15for(intr0;r3;r){if(grid[ir][j]grid[ir][j1]grid[ir][j2]!15){returnfalse;}}// 验证所有列的和为15for(intc0;c3;c){if(grid[i][jc]grid[i1][jc]grid[i2][jc]!15){returnfalse;}}// 验证主对角线和为15if(grid[i][j]grid[i1][j1]grid[i2][j2]!15){returnfalse;}// 验证副对角线和为15if(grid[i][j2]grid[i1][j1]grid[i2][j]!15){returnfalse;}returntrue;}}方法二预计算所有幻方importjava.util.*;classSolution{// 预计算所有8种3x3幻方通过旋转和镜像得到privatestaticfinalSetStringMAGIC_SQUARESnewHashSet();static{// 基础幻方int[][]base{{4,3,8},{9,5,1},{2,7,6}};// 生成所有8种变体generateAllMagicSquares(base);}/** * 生成所有8种幻方并添加到集合中 */privatestaticvoidgenerateAllMagicSquares(int[][]base){// 4种旋转int[][]currentcopyMatrix(base);for(inti0;i4;i){MAGIC_SQUARES.add(matrixToString(current));currentrotate90(current);}// 镜像后的4种旋转int[][]mirroredmirrorMatrix(base);currentcopyMatrix(mirrored);for(inti0;i4;i){MAGIC_SQUARES.add(matrixToString(current));currentrotate90(current);}}/** * 将3x3矩阵转换为字符串用于哈希 */privatestaticStringmatrixToString(int[][]matrix){StringBuildersbnewStringBuilder();for(inti0;i3;i){for(intj0;j3;j){sb.append(matrix[i][j]);}}returnsb.toString();}/** * 顺时针旋转90度 */privatestaticint[][]rotate90(int[][]matrix){int[][]rotatednewint[3][3];for(inti0;i3;i){for(intj0;j3;j){rotated[j][2-i]matrix[i][j];}}returnrotated;}/** * 水平镜像 */privatestaticint[][]mirrorMatrix(int[][]matrix){int[][]mirrorednewint[3][3];for(inti0;i3;i){for(intj0;j3;j){mirrored[i][j]matrix[i][2-j];}}returnmirrored;}/** * 复制矩阵 */privatestaticint[][]copyMatrix(int[][]matrix){int[][]copynewint[3][3];for(inti0;i3;i){System.arraycopy(matrix[i],0,copy[i],0,3);}returncopy;}publicintnumMagicSquaresInside(int[][]grid){introwsgrid.length;intcolsgrid[0].length;intcount0;for(inti0;irows-3;i){for(intj0;jcols-3;j){// 快速检查中心是否为5if(grid[i1][j1]!5){continue;}// 转换为字符串并检查是否在预计算集合中StringBuildersbnewStringBuilder();for(intr0;r3;r){for(intc0;c3;c){sb.append(grid[ir][jc]);}}if(MAGIC_SQUARES.contains(sb.toString())){count;}}}returncount;}}算法分析时间复杂度O((R-2) × (C-2)) O(R×C)R 和 C 是矩阵的行数和列数每个候选位置的验证是 O(1)固定3×3大小空间复杂度方法一O(1)只使用固定大小的数组方法二O(1)预计算的8个幻方是常数空间算法过程输入grid [[4,3,8,4],[9,5,1,9],[2,7,6,2]]矩阵尺寸3行4列可能的3×3子矩阵位置左上角 (0,0)检查中心grid[1][1] 5左上角 (0,1)检查中心grid[1][2] 1跳过验证位置 (0,0) 的3×3子矩阵4 3 8 9 5 1 2 7 6数字检查包含1-9各一次行和检查第0行43815第1行95115第2行27615列和检查第0列49215第1列35715第2列81615对角线检查主对角线45615副对角线85215结果1个幻方测试用例publicclassMain{publicstaticvoidmain(String[]args){SolutionsolutionnewSolution();// 测试用例1标准示例int[][]grid1{{4,3,8,4},{9,5,1,9},{2,7,6,2}};System.out.println(Test 1: solution.numMagicSquaresInside(grid1));// 1// 测试用例2无幻方int[][]grid2{{8}};System.out.println(Test 2: solution.numMagicSquaresInside(grid2));// 0// 测试用例3多个幻方int[][]grid3{{4,3,8,4,3,8},{9,5,1,9,5,1},{2,7,6,2,7,6}};System.out.println(Test 3: solution.numMagicSquaresInside(grid3));// 2// 测试用例4包含无效数字int[][]grid4{{10,3,8},{9,5,1},{2,7,6}};System.out.println(Test 4: solution.numMagicSquaresInside(grid4));// 0// 测试用例5重复数字int[][]grid5{{4,3,8},{9,5,1},{2,7,7}};System.out.println(Test 5: solution.numMagicSquaresInside(grid5));// 0// 测试用例6中心不是5int[][]grid6{{4,3,8},{9,4,1},{2,7,6}};System.out.println(Test 6: solution.numMagicSquaresInside(grid6));// 0// 测试用例7正确的幻方位置不同int[][]grid7{{0,0,0,0,0},{0,4,3,8,0},{0,9,5,1,0},{0,2,7,6,0},{0,0,0,0,0}};System.out.println(Test 7: solution.numMagicSquaresInside(grid7));// 1// 测试用例8边界情况 - 最小矩阵int[][]grid8{{4,3,8},{9,5,1},{2,7,6}};System.out.println(Test 8: solution.numMagicSquaresInside(grid8));// 1// 测试用例9旋转的幻方int[][]grid9{{2,9,4},{7,5,3},{6,1,8}};System.out.println(Test 9: solution.numMagicSquaresInside(grid9));// 1}}关键点数学3×3幻方中心必须是5只有8种可能的3×3幻方通过旋转和镜像验证顺序先检查中心是否为5O(1)快速过滤再检查数字范围和唯一性最后检查和的条件边界处理矩阵尺寸小于3×3时直接返回0数字必须严格在1-9范围内常见问题为什么3×3幻方中心必须是5在3×3幻方中中心位置参与4条线1行1列2对角线的计算而其他位置参与2-3条线。为什么只有8种3×3幻方所有3×3幻方都是同一个基础幻方通过旋转4种和镜像旋转4种得到的总共8种。