[LeetCode] 1139. Largest 1-Bordered Square
Given a 2D grid
of 0
s and 1
s, return the number of elements in the largest square subgrid that has all 1
s on its border, or 0
if such a subgrid doesn't exist in the grid
.
Example 1:
Input: grid = [[1,1,1],[1,0,1],[1,1,1]] Output: 9
Example 2:
Input: grid = [[1,1,0,0]] Output: 1
Constraints:
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j]
is0
or1
最大的以 1 为边界的正方形。
给你一个由若干 0 和 1 组成的二维网格 grid,请你找出边界全部由 1 组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/largest-1-bordered-square
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是前缀和。
这道题一开始我以为是跟 221 题类似的二维动态规划题,但是后来发觉不是,还是只能用前缀和的思路做。具体的做法是我先创建两个二维数组,分别记录每个 row 和每个 col 的前缀和,这样我就可以在 O(1) 的时间内知道某一段长度内是否都是 1。
因为能组成的最大的正方形的边长应该是 input 矩形较短的那一条边,设这个长度为 d。那么我们可以从 d 到 0 一点点去测试,看看哪个边长能被满足。因为 d 是从大到小遍历的,所以找到第一个满足条件的 d 就可以返回了。
时间O(m * n * d)
空间O(mn)
Java实现
1 class Solution { 2 public int largest1BorderedSquare(int[][] grid) { 3 int m = grid.length; 4 int n = grid[0].length; 5 int[][] rs = new int[m][n + 1]; 6 int[][] cs = new int[n][m + 1]; 7 for (int i = 0; i < m; i++) { 8 for (int j = 0; j < n; j++) { 9 rs[i][j + 1] = rs[i][j] + grid[i][j]; // 每行的前缀和 10 cs[j][i + 1] = cs[j][i] + grid[i][j]; // 每列的前缀和 11 } 12 } 13 14 for (int d = Math.min(m, n); d > 0; d--) // 从大到小枚举正方形边长 d 15 for (int i = 0; i <= m - d; i++) 16 for (int j = 0; j <= n - d; j++) // 枚举正方形左上角坐标 (i,j) 17 if (rs[i][j + d] - rs[i][j] == d && // 上边 18 cs[j][i + d] - cs[j][i] == d && // 左边 19 rs[i + d - 1][j + d] - rs[i + d - 1][j] == d && // 下边 20 cs[j + d - 1][i + d] - cs[j + d - 1][i] == d) // 右边 21 return d * d; 22 return 0; 23 } 24 }