持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
一、题目
LeetCode 最大正方形
二、题解
在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。
示例 1:
输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:4
示例 2:
输入:matrix = [["0","1"],["1","0"]]
输出:1
示例 3:
输入:matrix = [["0"]]
输出:0
方法一
我们可以直接遍历矩阵的元素,找到所有值为1的元素,然后以该值为1的元素为起点往外延伸找找一个正方形,即将该元素作为一个可能的正方形的左上角,根据这个左上角往下和右移动,每次加1个元素的大小,判断其之后的行元素以及列元素是否都为1,这样可以找到一个正方形的长度,最后就保留最大的正方形长度,正方形大小就是长度的平方了。具体的遍历矩阵元素,如果当前元素值为1的话,就可以寻找可能的最大正方形,但是需要注意不要越界,如果元素都是1那么就更新最大边长的值,最后遍历结束返回最大边长的平方即可。
方法二
或者可以考虑使用动态规划,定义与矩阵matrix相同大小的二维数组dp,dp[i][j]表示以[i][j]为右下角的正方形最大边长,同时需要一个变量maxSide记录最大的边长。那么对于矩阵的第一行元素,如果其值为1,那么就初始化dp对应位置的值为1,同时更新最大边长maxSide;同样的对与第一列的元素,如果其值为1,那么也将dp对于位置的值设置为1,同时更新最大边长maxSide的值。对于其他位置的元素如果值为1的话,以[i][j]为右下角的正方形而言的最大边长为左边、左上角、上边三个位置的正方形中最小的一个边长加上当前位置+1,同时更新最大边长。最后只需返回最大边长的一个平方。
三、代码
方法一 Java代码
class Solution {
public int maximalSquare(char[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int maxSide = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
maxSide = Math.max(maxSide, 1);
int border = Math.min(m - i, n - j);
se:
for (int k = 1; k < border; k++) {
for (int l = 0; l <= k; l++) {
if (matrix[i + k][j + l] == '0' || matrix[i + l][j + k] == '0') {
break se;
}
}
maxSide = Math.max(maxSide, k + 1);
}
}
}
}
return maxSide * maxSide;
}
}
时间复杂度:O(n^4),首先需要遍历二维数组的每一个元素,然后如果元素值为1则继续以该元素为起点遍历其周围元素。
空间复杂度:O(1),只需常数空间。
方法二 Java代码
class Solution {
public int maximalSquare(char[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int maxSide = 0;
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) {
if (matrix[i][0] == '1') {
dp[i][0] = 1;
maxSide = Math.max(maxSide, dp[i][0]);
}
}
for (int i = 0; i < n; i++) {
if (matrix[0][i] == '1') {
dp[0][i] = 1;
maxSide = Math.max(maxSide, dp[0][i]);
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == '1') {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
maxSide = Math.max(maxSide, dp[i][j]);
}
}
return maxSide * maxSide;
}
}
时间复杂度:O(n^2),需要遍历一次矩阵的所有元素
空间复杂度:O(n^2),使用了与矩阵同等大小的dp数组。