LeetCode840:矩阵中的幻方

110 篇文章 0 订阅

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

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

示例 1:

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

而这一个不是:
384
519
762

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

提示:

  1. 1 <= grid.length = grid[0].length <= 10
  2. 0 <= grid[i][j] <= 15

解析:

        该题目,主要分为两个步骤,一个是将原矩阵,划分为若干个3*3的矩阵,第二步是判断3*3的矩阵是否是幻阵。在划分的时候注意矩阵是否可划分,即行列是否都大于等于3,还要注意最后一个划分起点的位置。判断幻阵时,注意是否有重复元素和大于9的元素,然后只需要判断第一行,第一列,第一个对角线和第二行,第二列即可,不需要所有行列对角线都判断,因为这5个已经涵盖了所有元素。

代码:

//判断是否幻阵
bool isMagicSquares(vector<vector<int>>& subGrid)
{
	set<int>sGrid;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			sGrid.insert(sGrid.begin(), subGrid[i][j]);
		}
	}
//用set判断是否有重复元素和大于9的元素
	if (sGrid.size() < 9 || *(--sGrid.end()) > 9)
		return false;
	if (subGrid[0][0] + subGrid[0][1] + subGrid[0][2] != 15)
		return false;
	if (subGrid[0][0] + subGrid[1][1] + subGrid[2][2] != 15)
		return false;
	if (subGrid[0][0] + subGrid[1][0] + subGrid[2][0] != 15)
		return false;
	if (subGrid[1][0] + subGrid[1][1] + subGrid[1][2] != 15)
		return false;
	return true;
}

int numMagicSquaresInside(vector<vector<int>>& grid) 
{
	vector<vector<int>>subGrid(3,vector<int>(3));
	int rows = grid.size();
	int cols = grid[0].size();
	if (rows < 3 || cols < 3)
		return 0;
	int res = 0;
	for (int i = 0; i < rows - 2; i++)
	{
		for (int j = 0; j < cols - 2; j++)
		{
			subGrid[0][0] = grid[i][j];
			subGrid[0][1] = grid[i][j+1];
			subGrid[0][2] = grid[i][j+2];
			subGrid[1][0] = grid[i+1][j];
			subGrid[1][1] = grid[i+1][j+1];
			subGrid[1][2] = grid[i+1][j+2];
			subGrid[2][0] = grid[i+2][j];
			subGrid[2][1] = grid[i+2][j+1];
			subGrid[2][2] = grid[i+2][j+2];
			if (isMagicSquares(subGrid))
				res++;
		}
	}
	return res;
}
int numMagicSquaresInside(vector<vector<int>>& grid) 
{
        int row=grid.size();
        int col=grid[0].size();
        
        int count=0;
        set<int>s;
        for(int i=1;i<row-1;i++)
        {
            for(int j=1;j<col-1;j++)
            {
                if(grid[i][j]!=5)//幻方中间必须为5
                    continue;
                s.insert(s.begin(),grid[i-1][j-1]);
                s.insert(s.begin(),grid[i-1][j]);
                s.insert(s.begin(),grid[i-1][j+1]);
                s.insert(s.begin(),grid[i][j-1]);
                s.insert(s.begin(),grid[i][j]);
                s.insert(s.begin(),grid[i][j+1]);
                s.insert(s.begin(),grid[i+1][j-1]);
                s.insert(s.begin(),grid[i+1][j]);
                s.insert(s.begin(),grid[i+1][j+1]);
                if(s.size()!=9)//判断是否有重复元素
                { 
                    s.clear();
                    continue;
                }
                if(*s.begin()!=1)//判断数字为1-9
                {
                    s.clear();
                    continue;
                }
                    
                if(*s.end()!=9)
                 {
                    s.clear();
                    continue;
                }
                s.clear();
                if((grid[i][j]+grid[i-1][j-1]+grid[i+1][j+1]==15)
                  &&(grid[i][j]+grid[i-1][j]+grid[i+1][j]==15)
                  &&(grid[i][j]+grid[i-1][j+1]+grid[i+1][j-1]==15)
                  &&(grid[i][j]+grid[i][j-1]+grid[i][j+1]==15)
                    &&(grid[i-1][j]+grid[i-1][j-1]+grid[i-1][j+1]==15)
                    &&(grid[i+1][j]+grid[i+1][j-1]+grid[i+1][j+1]==15)
                    &&(grid[i-1][j-1]+grid[i][j-1]+grid[i+1][j-1]==15)
                    &&(grid[i-1][j+1]+grid[i][j+1]+grid[i+1][j+1]==15)
                  )
                    count++;
            }
        }
        return count;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值