题目来源:LeetCode第1139题
难度:中等
题目描述:
给你一个由若干0和1组成的二维网格grid,请你找出边界全部由1组成的最大正方形子网格,并返回该子网格中的元素数量。如果不存在,则返回0。
示例 1:
输入:grid = [
[1,1,1],
[1,0,1],
[1,1,1]]
输出:9
示例 2:
输入:grid = [[1,1,0,0]]
输出:1
提示:
1<=grid.length<=100
1<=grid[0].length<=100
grid[i][j]为0或1
只要搞懂动态规划的原理,代码就非常简洁。而这题只要正方形4条边的网格都是1即可,中间是什么数字不用管
解题思路是这样的:
1.先计算每个网格(i,j)的左边和上边连续1的个数。
2.遍历二维网格,以每一个格子(i,j)为正方形的右下角,分别找出这个(i,j)格子上边的格子和左边的格子连续1的个数,取最小值作为正方形的边长cursize,然后判断此时以cursize为边长的正方形的左边长和上边长是否都大于等于正方形边长,如果都大于等于正方形边长说明符合正方形条件,可以更新maxsize,否则缩小正方形的边长,继续判断……。
定义一个三维数组,用来记录格子(i,j)左边连续1个数和上边连续1个数。
dp[i][j][0]: (i,j)左边连续1的个数
dp[i][j][1]: (i,j)上边连续1的个数
分别沿着左边和上边找出他们连续1的个数,最小的作为正方形的边长。因为左边和上边连续1的个数我们在第一步的时候已经计算过,分别是dp[i][j][0]和dp[i][j][1],也就是正方形的边长我们暂时可以认为是
cursize = Math.min(dp[i][j][0], dp[i][j][1]);
确定好初始的正方形边长后,我们还需要验证这个正方形的左边和上边是否符合,如果符合,则更新maxsize,否则就缩小正方形边长,继续寻找符合的情况。
这种情况上边和左边的长度均大于cursize = 3 ,所以更新maxsize
这种情况正方形的上边不是连续1,不符合正方形条件。缩小正方形边长,继续寻找。
贴代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int Grid[100][100]; //给定的2维网格
int dp[101][101][2];
//dp[i][j][0]: (i,j)横向连续1的个数 这里的(i,j)指的是第i,j个格子 对应下标+1
//dp[i][j][1]: (i,j)竖向连续1的个数
int maxsize = 0; //全局变量,统计所有正方形的最大边长
int Min(int x,int y)
{
return x>y?y:x;
}
int GetSquare_size(int grid[100][100],int m,int n){
int i,j;
//以每个格子为正方形的右下角,计算这个格子左边和上边的连续1的个数
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(grid[i-1][j-1]==0) // 0不计入边长
continue;
else if(grid[i-1][j-1]==1)
{
dp[i][j][0] = dp[i][j-1][0] + 1;
dp[i][j][1] = dp[i-1][j][1] + 1;
}
}
}
int cursize = 0;
for(i=1;i<=m;i++) //维持maxsize变量 动态更新正方形的最大长度
{
for(j=1;j<=n;j++)
{
cursize = Min(dp[i][j][0],dp[i][j][1]); //以(i,j)为右下角的正方形的初始边长
//判断此时正方形的左下角格子的竖向边长 和 右上角的格子的横向边长是否都大于cursize
//若均大于 cursize即为一个满足的正方形边长
while(cursize)
{
if(dp[i][j-cursize+1][1]>=cursize && dp[i-cursize+1][j][0]>=cursize) //符合正方形条件
{
if(cursize >= maxsize)
maxsize = cursize;
break; //
}
cursize --; //若不符合正方形条件,说明边长cursize的正方形有条边不是连续1 则缩小cursize 继续判断
}
}
}
return maxsize;
}
int main()
{
int m,n;
int i,j;
scanf("%d %d",&m,&n); //m*n的二维网格
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&Grid[i][j]);
int Square_size = GetSquare_size(Grid,m,n);
printf("The square area is%d",Square_size*Square_size);
return 0;
}
结果展示: