一、题目解析
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 <= grid.length = grid[0].length <= 10
0 <= grid[i][j] <= 1
二、解法分析
幻方的几个要素 (也就是3*3的矩阵):
1、中心元素必定为5,
2、其实这个幻方一共有8中,只要有一个解,其他的解可以通过矩阵变换来的得到,比如:这个幻方
438 951 276
我们可以通过对矩阵就转秩,就可以得到另外一个幻方,
3、也可以通过顺时针旋转90度,得到另外一个解。
利用这三个要素就可以解决本题了,步骤如下:
1、在数据中寻找中心元素5
2、判断以这个中心元素为5的3*3的子矩阵是否为幻方
代码如下:
class Solution {
public:
int numMagicSquaresInside(vector<vector<int>>& grid) {
if(grid[0].size() < 3 || grid.size() < 3)
return 0;
int cnt = 0;
for(int i = 1; i < grid.size() - 1; i++){
for(int j = 1; j < grid[i].size() - 1; j++){
if(grid[i][j] == 5){ //判断中心元素是否为5
if(isMagic(grid, i, j)) //判断是否为幻方
cnt++;
}
}
}
return cnt;
}
bool isMagic(vector<vector<int>> &grid, int i, int j){
vector<vector<int>> magic(3,vector<int>(3));
magic[0][0] = 4;
magic[0][1] = 3;
magic[0][2] = 8;
magic[1][0] = 9;
magic[1][1] = 5;
magic[1][2] = 1;
magic[2][0] = 2;
magic[2][1] = 7;
magic[2][2] = 6; //magic代表一个幻方
for(int k = 0; k < 4; k++){
rotating(magic); //顺时针旋转90度后,形成另一个幻方
if(grid[i-1][j-1] == magic[0][0] && grid[i-1][j] == magic[0][1] && grid[i-1][j+1] == magic[0][2] && grid[i][j-1] == magic[1][0] && grid[i][j + 1] == magic[1][2] && grid[i+1][j-1] == magic[2][0] && grid[i+1][j] == magic[2][1] && grid[i+1][j+1] == magic[2][2])
return true;
sym(magic); //转秩后,形成另一个幻方
if(grid[i-1][j-1] == magic[0][0] && grid[i-1][j] == magic[0][1] && grid[i-1][j+1] == magic[0][2] && grid[i][j-1] == magic[1][0] && grid[i][j + 1] == magic[1][2] && grid[i+1][j-1] == magic[2][0] && grid[i+1][j] == magic[2][1] && grid[i+1][j+1] == magic[2][2])
return true;
sym(magic);
}
return false;
}
void sym(vector<vector<int>> &mt){
for(int i = 0; i < 3; i++){
for(int j = i; j < 3; j++){
if(j != i){
int tmp = mt[i][j];
mt[i][j] = mt[j][i];
mt[j][i] = tmp;
}
}
}
}
void rotating(vector<vector<int>> &mt){
for(int i = 0; i < 3; i++){
for(int j = i; j < 3; j++){
if(j != i){
int tmp = mt[i][j];
mt[i][j] = mt[j][i];
mt[j][i] = tmp;
}
}
}
for(int i = 0 ; i < 3; i++){
int tmp = mt[i][0];
mt[i][0] = mt[i][2];
mt[i][2] = tmp;
}
}
};
运行时间:4ms