1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法
给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold。
请你返回元素总和小于或等于阈值的正方形区域的最大边长;如果没有这样的正方形区域,则返回 0 。
示例 1:
输入:mat = [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[1,1,3,2,4,3,2]], threshold = 4
输出:2
解释:总和小于或等于 4 的正方形的最大边长为 2,如图所示。
示例 2:
输入:mat = [[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2]], threshold = 1
输出:0
像在矩阵中使用前缀和算法,难点并不是算法思路而是实现过程,当矩阵很大的时候,我们需要一遍一遍的去推导数据流向。
这一题可谓是非常精彩,这一题,可以作为一个模板,这样可以解决很多图的问题和二维矩阵的问题,需要一些数学推导,核心还是在于前缀和的计算,解题代码如下:
bool find(int **presum,int n,int m,int c,int threshold){
printf("-- %d %d %d ",m,n,c);
for(int j=0;j<=m-c;j++){
for(int i=0;i<=n-c;i++){
int a,b;
int d;
if(i==0||j==0){
d=0;
}
else{
d=presum[i-1][j-1];
}
if(j==0){
a=0;
}
else{
a=presum[i-1+c][j-1];
}
if(i==0){
b=0;
}
else{
b=presum[i-1][j-1+c];
}
int sum=presum[c+i-1][c+j-1]-a-b+d;
if(sum<=threshold){
return true;
}
}
}
return false;
}
int maxSideLength(int** mat, int matSize, int* matColSize, int threshold){
int n=matSize,m=matColSize[0];
int **presum=(int **)malloc(sizeof(int *)*matSize);
for(int i=0;i<matSize;i++){
presum[i]=(int *)malloc(sizeof(int)*matColSize[0]);
}
int col=1,rol=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
presum[i][j]=0;
}
}
presum[0][0]=mat[0][0];
while(col!=m&&rol!=n){
if(rol==0){
for(int i=col;i<m;i++){
presum[rol][i]=presum[rol][i-1]+mat[rol][i];
}
rol++;
}
else{
for(int i=col;i<m;i++){
presum[rol][i]=presum[rol][i-1]+mat[rol][i]+presum[rol-1][i]-presum[rol-1][i-1];
}
rol++;
} if(col==1){
for(int i=1;i<n;i++){
presum[i][0]=presum[i-1][0]+mat[i][0];
}
}
else{
for(int i=rol;i<n;i++){
presum[i][col]=presum[i-1][col]+mat[i][col]+presum[i][col-1]-presum[i-1][col-1];
}
col++;
}
}
int max=0;
for(int i=1;i<=fmin(m,n);i++){
if(find(presum,n,m,i,threshold)){
max=i;
}
else{
break;
}
}
// for(int i=0;i<n;i++){
// // printf("||");
// for(int j=0;j<m;j++){
// // printf("%d ",presum[i][j]);
// }
// }
return max;
}