题目描述
给你一个由若干 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
思路
根据以往的思路,我们如果能计算出每个点出发,往 上下左右 四个方向上连续1的最大长度,就能遍历出解。我们把4个方法的长度可以记录为4个二维数组:up[i][j]、down[i][j]、left[i][j]、right[i][j]分成代表坐标为(i,j)的点在4个方法上的二维数组,那么我们可以根据max(right[i][j]、down[i][j])获取点(i,j)作为左上角顶点的正方形最大长度len,然后再去验证右下角的点(i+len, j+len)的up[i+len][j+len] 和 left[i+len][j+len]是否能满足大于等于len即可。如果不能满足,就再验证len-1。
用上面的方法确实可以切除解,不过略显繁琐,其实我们转换一下,只要2个方向的数组up[i][j]、left[i][j]即可。把(i,j)设置为右下角顶点,然后分别去验证(i-len,j)的up[i-len][j] 和 (i,j-len)的left[i][j-len]是否满足大于等于len即可。
Java版本代码
class Solution {
public int largest1BorderedSquare(int[][] grid) {
int m = grid.length, n = grid[0].length;
int[][] left = new int[m + 1][n + 1];
int[][] up = new int[m + 1][n + 1];
int maxBorder = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (grid[i - 1][j - 1] == 1) {
left[i][j] = left[i][j - 1] + 1;
up[i][j] = up[i - 1][j] + 1;
int border = Math.min(left[i][j], up[i][j]);
while (left[i - border + 1][j] < border || up[i][j - border + 1] < border) {
border--;
}
maxBorder = Math.max(maxBorder, border);
}
}
}
return maxBorder * maxBorder;
}
}
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情