最大的以 1 为边界的正方形
难度:
标签:
题目描述
代码结果
运行时间: 43 ms, 内存: 16.5 MB
/*
* 思路:
* Java Stream不适合用来处理二维数组的动态规划问题,因此这里采用基本相同的思路来实现算法,
* 但是无法完全集成Java Stream来实现。主要思路是利用动态规划思想和条件判断来寻找最大正方形边长。
*/
import java.util.stream.IntStream;
public class SolutionStream {
public int largest1BorderedSquare(int[][] grid) {
int rows = grid.length;
int cols = grid[0].length;
int[][] top = new int[rows + 1][cols + 1];
int[][] left = new int[rows + 1][cols + 1];
int maxLen = 0;
IntStream.range(1, rows + 1).forEach(i -> {
IntStream.range(1, cols + 1).forEach(j -> {
if (grid[i - 1][j - 1] == 1) {
top[i][j] = top[i - 1][j] + 1;
left[i][j] = left[i][j - 1] + 1;
int len = Math.min(top[i][j], left[i][j]);
while (len > 0) {
if (left[i - len + 1][j] >= len && top[i][j - len + 1] >= len) {
maxLen = Math.max(maxLen, len);
break;
}
len--;
}
}
});
});
return maxLen * maxLen;
}
}
解释
方法:
该题解采用动态规划的思想。首先,创建两个二维数组row和col,其中row[i][j]表示在grid[i][j]处,从该点向左连续的1的数量;col[i][j]表示在grid[i][j]处,从该点向上连续的1的数量。然后,遍历整个网格,对于每一个点(grid[i][j] == 1),我们检查以该点为右下角的正方形的最大边长。这里的最大边长取决于从该点向左和向上连续的1的数量(即row[i][j]和col[i][j]的较小值)。对于可能的每个边长,我们检查相应的左边界和上边界是否满足条件(即是否包含足够数量的连续的1)。如果满足条件,我们更新最大正方形的边长。最后,返回最大边长的平方,即最大正方形中的元素数量。
时间复杂度:
O(mn * min(m, n))
空间复杂度:
O(mn)
代码细节讲解
🦆
在初始化row和col数组时,为什么只需要考虑向左或向上的连续1的数量,而不是四个方向?
▷🦆
动态规划解决这个问题的关键在哪里?具体是如何通过前面的状态推导出后面状态的?
▷🦆
你是如何确定检查每个可能的边长时的停止条件的?为什么是在当前最大边长大于等于max_l时才停止?
▷🦆
为什么在检查左边界和上边界是否包含足够数量的连续的1时,只需要检查row[x][j]和col[i][y]?
▷