1292. 元素和小于等于阈值的正方形的最大边长-前缀和算法

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值