目录
题目一:1975. 最大方阵和
问题描述:
给你一个 n x n 的整数方阵 matrix 。你可以执行以下操作 任意次 :
选择 matrix 中 相邻 两个元素,并将它们都 乘以 -1 。
如果两个元素有 公共边 ,那么它们就是 相邻 的。你的目的是 最大化 方阵元素的和。请你在执行以上操作之后,返回方阵的 最大 和。
解题思路:
首先需要知道一个前提就是,矩阵中的任意的两个数都可以通过操作之后变换成正数,无论它们的位置如何(具体方法是选定两个负数,在它们之间连一条线,通过线不断将两个负号往中间靠拢,直至一条线都变成正数)。所以,如果负数的个数为偶数,那么所有的负数可以变成正数,反之,则会有一个负数落单。
同样地,如果矩阵之中有0,那么所有的负数都可以变成正数,0和任意负数连线。
因此我们的思路就变成了:
①判断矩阵中是否有0,有就计算所有元素的绝对值之和
②计算负数的个数,如果为偶数,就计算所有元素的绝对值之和
如果为奇数,那么把所有元素绝对值之和减去 元素中绝对值最小的,这里有点贪心的思想。
代码:
long long maxMatrixSum(int** matrix, int matrixSize, int* matrixColSize){
int r, c = matrixSize;
int i, j;
long long res = 0;
for(i=0; i<r; i++) //计算所有元素绝对值之和
{
for(j=0; j<c; j++)
{
res +=abs(matrix[i][j]);
}
}
long long max_ = 0;
int cnt = 0; //计数器
int how = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
if(matrix[i][j] == 0) //如果有0,则直接输出res
{
how = 1;
}
if(matrix[i][j] < 0) //计算负数的个数
{
cnt++;
}
}
}
for(i=0; i<r; i++) //绝对值之和减去绝对值最小的元素
for(j=0; j<c;j++)
{
max_ = fmax(max_, res-abs(matrix[i][j]) );
}
if(how == 1)
return res;
else
{
if(cnt % 2 == 0)
return res;
else
return max_;
}
}
题目二:840. 矩阵中的幻方
3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。
给定一个由整数组成的row x col 的 grid,其中有多少个 3 × 3 的 “幻方” 子矩阵?(每个子矩阵都是连续的)。
解题思路:
①以任意一个元素为起点,判断3 x 3的行和和列和是否相等
②判断主副对角线是否相等
③判断每行每列以及对角线出现的数字在1-9之间,并且两两不重复(用哈希表计算每个数字出现的个数)
因为条件多,所以代码量也会有点多,但是思路总体不会很难
代码:
int Is_Magic(int **grid, int x, int y)
{
int sum = grid[x][y] + grid[x][y+1] + grid[x][y+2];
for(int i=0;i<3;++i){
//统计行和
if(sum != grid[x+i][y]+grid[x+i][y+1]+grid[x+i][y+2])
return 0;
//统计列和
if(sum != grid[x][y+i]+grid[x+1][y+i]+grid[x+2][y+i])
return 0;
}
//判断对角线
if(sum != grid[x][y]+grid[x+1][y+1]+grid[x+2][y+2])
return 0;
if(sum != grid[x][y+2] +grid[x+1][y+1]+grid[x+2][y])
return 0;
//判断1-9是否重复出现以及是否数字不在1-9范围内
int hash[10];
memset(hash,0,sizeof(int)*10);
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
{
if(grid[x+i][y+j] <1 || grid[x+i][y+j] > 9)
return 0;
++hash[grid[x+i][y+j]];
}
for(int i=1; i<=9; i++)
if(hash[i] != 1)
return 0;
return 1;
}
int numMagicSquaresInside(int** grid, int gridSize, int* gridColSize){
int r = gridSize;
int c = gridColSize[0];
int i, j;
int res = 0;
if(r<3 || c<3)
return 0;
//遍历矩阵
for(i=0; i<r-2; i++)
for(j=0; j<c-2; j++)
if(Is_Magic(grid, i, j))
res+= 1;
return res;
}