1. 题目与解析
给你一个由若干 0
和 1
组成的二维网格 grid
,请你找出边界全部由 1
组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0
。
输入: grid = [[1,1,1],[1,0,1],[1,1,1]]
输出: 9
输入: grid = [[1,1,0,0]]
输出: 1
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j]
为0
或1
题意很简单,但是往往,越简单的题目表述越容易让人一头雾水,找不到解题的关键。
为了找到解题的思路,我们就需要梳理何种条件下,我们可以计算出题目的答案。
对于一个点(i,j),我们将其视为一个正方形的点,在判断其是否可以组成正方形时,我们需要做的是判断能不能形成四条对应的边.
首先(i,j)为0时,肯定不可以为1时,其存在横线与纵向两条边,这两条边的最小值就可以作为边长d。
有了一个点以及边长,我们就可以确定其横向与纵向相邻的两个点(i+d,j),(i,j+d)。
之后,再通过相邻的两个点与对角线上的点(i+d,j+d)判断另外的两条边是否存在即可。
思路确定了,判断边存不存在就是判断两点之间是否都为1,这个过程会存在重复计数的情况,为了避免这一问题的发生,我们可以借助一个二维的dp表格,用动态规划的方式,分别统计横向与纵向相邻的1的个数,之后用之前提到的判断逻辑进行计算解题即可。
2. 题解
public int largest1BorderedSquare(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][][] dp = new int[m+1][n+1][2];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (grid[i-1][j-1] == 1){
dp[i][j][0] = 1 + dp[i][j-1][0];
dp[i][j][1] = 1 + dp[i-1][j][1];
}
}
}
int res = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
for (int side = Math.min(dp[i][j][0], dp[i][j][1]); side >= 1; side--){
if (dp[i][j-side+1][1] >= side && dp[i-side+1][j][0] >= side){
res = Math.max(res, side);
break;
}
}
}
}
return res * res;
}