开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的29天,点击查看活动详情
题目: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
提示:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 300matrix[i][j]为'0'或'1'
解题思路
取矩阵行数为 m,列数为 n,行索引i,从0 到 m−1,列索引从 0 到n−1
遍历矩阵,对于每个为'1'的元素,以它为左上角,来搜索最大的正方形,遍历完成后即能找到最大的正方形。
为了方便,返回正方形的边长,这是为了方便做剪枝,如果边长大于最小边(即m和n)的一半,那么当前找到的正方形一定是全局最大的,不可有比它再大的了,所以可以停止遍历了。
具体说下搜索最大正方形的过程:以[i,j]为左上角,向左下去搜索,那么最大的可能的边长就是min(m−i,n−j)−1了,记为maxLen。可能的边长len,从1开始增长到maxLen,然后检查外面增加一行和一列是否全是'1',如果是,len就加1,直到遇到有'0'或者到达maxLen为止。如此便能找到以[i,j]为左上的最大正方形,边长即是len。
暂时没有想到,优化方法,想着可能像DFS那样,把搜索过的地方做个标记,这样可以重复查找,但这有问题,因为正方形可能会有重叠,这会导致后面的正方形面积缩小。
代码实现
private int m;
private int n;
public int maximalSquare(char[][] matrix) {
m = matrix.length;
n = matrix[0].length;
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
int len = calcArea(matrix, i, j);
maxArea = Math.max(len * len, maxArea);
if (len > (Math.min(m, n) / 2 + 1)) {
return maxArea;
}
}
}
}
return maxArea;
}
private int calcArea(char[][] matrix, int i, int j) {
int maxLen = Math.min(m - i, n - j) - 1;
int len = 1;
for (; len <= maxLen; len++) {
boolean allOne = true;
for (int x = i; x <= i + len; x++) {
if (matrix[x][j + len] == '0') {
allOne = false;
break;
}
}
if (allOne) {
for (int y = j; y <= j + len; y++) {
if (matrix[i + len][y] == '0') {
allOne = false;
break;
}
}
}
if (!allOne) {
break;
}
}
return len;
}
运行结果
复杂度分析
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN) 一起分享知识, Keep Learning!