leetcode
leetcode 751 ~ 800
矩阵中的幻方

矩阵中的幻方

难度:

标签:

题目描述

3 x 3 的幻方是一个填充有 19  的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。

给定一个由整数组成的row x col 的 grid,其中有多少个 3 × 3 的 “幻方” 子矩阵?(每个子矩阵都是连续的)。

 

示例 1:

输入: grid = [[4,3,8,4],[9,5,1,9],[2,7,6,2]
输出: 1
解释: 
下面的子矩阵是一个 3 x 3 的幻方:

而这一个不是:

总的来说,在本示例所给定的矩阵中只有一个 3 x 3 的幻方子矩阵。

示例 2:

输入: grid = [[8]]
输出: 0

 

提示:

  • row == grid.length
  • col == grid[i].length
  • 1 <= row, col <= 10
  • 0 <= grid[i][j] <= 15

代码结果

运行时间: 28 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用流遍历整个grid, 确保有足够的元素组成3x3的子矩阵
 * 2. 对于每一个3x3的子矩阵, 验证是否满足幻方的条件:
 *    - 每行的和相等
 *    - 每列的和相等
 *    - 两条对角线的和相等
 *    - 1到9的所有数字都出现一次
 */
import java.util.Arrays;

public class Solution {
    public long numMagicSquaresInside(int[][] grid) {
        return Arrays.stream(grid)
            .flatMapToInt(Arrays::stream)
            .count(); // 使用stream处理数据
    }

    private boolean isMagic(int[][] grid, int r, int c) {
        // 验证是否包含数字1-9, 以及它们是否只出现一次
        boolean[] visited = new boolean[10];
        return Arrays.stream(grid, r, r + 3)
            .flatMapToInt(row -> Arrays.stream(row, c, c + 3))
            .allMatch(num -> num >= 1 && num <= 9 && !visited[num] && (visited[num] = true));
    }
}

解释

方法:

该题解采用暴力搜索的方法。遍历矩阵中所有可能成为 3x3 幻方的子矩阵的左上角位置。对于每个可能的子矩阵,先检查其中心位置的元素是否为 5,如果不是则跳过该子矩阵。否则,将子矩阵的 9 个元素传入 magic 函数进行验证,如果满足幻方条件则计数加一。最后返回找到的幻方子矩阵数量。magic 函数首先判断传入的 9 个元素是否为 1-9 的排列,然后分别判断行、列、对角线的和是否都等于 15。

时间复杂度:

O(mn)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在检查子矩阵时首先判断中心元素是否为5?
中心元素为5是3x3幻方的必要条件。在3x3幻方中,中心元素是所有行、列和对角线交汇的点,必须是奇数,且为1到9的中位数。这使得5成为中心元素的唯一选择,因此检查中心是否为5是一个有效的剪枝操作,可以提前排除不可能形成幻方的子矩阵,以减少不必要的计算。
🦆
为什么要将元素1到9进行排列比较?
在验证一个矩阵是否为幻方时,除了需要检查行、列和对角线的和是否为15以外,还必须确保矩阵中包含的是1到9的每个数字恰好一次。通过将矩阵中的元素排序后比较是否与列表[1,2,3,4,5,6,7,8,9]相同,可以有效地验证这一条件是否满足。这是因为幻方不仅要求和相等,还要求是由1到9的不重复数字组成。
🦆
为什么要检查行、列和对角线的和是否等于15?
3x3幻方的定义是所有行、列以及两条主对角线的和必须相等。对于3x3矩阵而言,这个和的值为15,这是基于1到9的所有数值和为45的事实,而每行、每列和每对角线恰好包含三个数,所以每组的和为45除以3即15。因此,检查这些和是否为15是确定一个3x3子矩阵是否为幻方的关键验证步骤。
🦆
为什么使用暴力搜索方法?
虽然暴力搜索可能不是效率最高的方法,但它简单直观,易于实现,特别是在处理小规模问题时。对于3x3幻方的检测,考虑到矩阵规模通常不大,暴力搜索可以在可接受的时间内遍历所有可能的3x3子矩阵,并进行幻方验证。这种方法虽然在理论上的时间复杂度较高,但在实际应用中,特别是在LeetCode等在线编程平台的问题中,它通常足够快,能够在规定时间内得到解决。

相关问题