1、数据结构:整形数字 maxArea,用于记录当前遍历到的最大面积。
2、 深度优先搜索 DFS:每当访问到1时,以此点为左上角分别对长和宽开始搜索,计数得到的两个数字取其中较小的为正方形的边长,平方运算后即正方形的面积。
问题:
1. 没有意识到,最大面积正方形应该由 ‘1’ 填充,仅遍历长宽会导致如下问题,长宽对应的两条边由 '1' 组成,但正方形内部缺存在 ‘0’,这时这个正方形不满足条件。
解决:想到了递归,大正方形必然套在小正方形外一层,每个小正方形,若外围均为 ‘1’ 或者为边界,那么就可以构成更大的正方形。
问题:想打复杂,编程实现较为困难
解决:看了相关的题解,想到之前做过的直方图的方法,并不需要两个边同时向外搜索,固定正方形一边的长度,看另一边是否满足该长度即可(可通过1累加的值是否等于固定长判断),过程像累加了一个直方图,具体流程如下:
数据结构:一维数组v,存储直方图向下的长度
- 选定一行 i,从该行开始向下遍历各行,若matrix[i][k]=='1',令v[k]++。
- 当遍历当行i+n时,检测是否存在边长为n的正方形。
- 遍历v,检测v[k]到v[k+n]之间的v[k']的值是否均为 n。
- 若是,存在长度为n的正方形,否则不存在。
Go
func maximalSquare(matrix [][]byte) int {
var res, m, n int=0, len(matrix), len(matrix[0])
var getMax func(a, b int)int
getMax=func(a, b int)int{
if a>=b { return a } else { return b }
}
for i:=0; i<m; i++{
var v []int=make([]int, n)
for j:=i; j<m; j++{
for t:=0; t<n; t++{
if matrix[j][t]=='1'{ v[t]++ }
}
l, c:=j-i+1, 0
for _, v_:=range v{
if v_==l {c++} else{ c=0 }
if c==l {res=getMax(res, l*l)}
}
}
}
return res
}
Java
class Solution {
public int maximalSquare(char[][] matrix) {
int res=0;
int m=matrix.length;
int n=matrix[0].length;
for(int i=0; i<m; i++){
int[] v=new int[n];
for(int j=i; j<m; j++){
for (int t=0; t<n; t++){
if(matrix[j][t]=='1'){ v[t]++; }
}
int l=j-i+1;
int c=0;
for(int k=0; k<v.length; k++){
if(v[k]==l){
c++;
} else{ c=0; }
if(c==l){ res=Math.max(res, l*l); }
}
}
}
return res;
}
}