leetcode-最大的以 1 为边界的正方形

128 阅读1分钟

题目描述

给你一个由若干 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 天,点击查看活动详情