在一个二维01矩阵中找到全为1的最大正方形
样例
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
返回 4
分析
(1)方法一:一般性方法,可以扩展到最大矩形计算
1、以每一行为矩形底,计算每一列的含1的行高
2、遍历行高,按照递增入栈,一旦栈顶小于当前行高,出栈,并计算出栈高度左右最远扩展的长度(即矩形宽度) = 当前下标-栈顶下标-1
(2)方法二:动态规划
大正方形由小正方形构成
//当(i-1,j-1)、(i,j-1)、(i-1,j)非0时,(i,j)可以构成正方形,且变成为前3点的最短边长
if(matrix[i-1][j-1]>0 && matrix[i-1][j]>0 && matrix[i][j-1]>0 && matrix[i][j]>0)
matrix[i][j] = Math.min(matrix[i-1][j-1], Math.min(matrix[i-1][j],matrix[i][j-1]))+1;
代码
public class Solution {
/**
* @param matrix: a matrix of 0 and 1
* @return: an integer
*/
//一般性方法,可以扩展到最大矩形计算
//TC = O(m*n)
//SC = O(m)
public int maxSquare_nor(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
//第i行
int[] height = new int[n+1];
int max=0;
for(int i=0; i<m; i++){
//计算i行的含1的高度
for(int j=0; j<n; j++){
if(matrix[i][j]==1)
height[j]+=1;
else
height[j]=0;
}
max = Math.max(max, countMax(height));
}
return max;
}
int countMax(int[] height){
int n = height.length;
Stack<Integer> s = new Stack<Integer>();
s.add(0);
int i=1, max=0;
while(i<n || !s.isEmpty()){
//高度比栈顶大就入栈
if(i<n && (s.isEmpty() || height[i]>=height[s.peek()])){
s.add(i);
i++;
}else{
//当前高度比peek小,弹出peek
//计算tPeek能扩展的宽度
int tPeek = s.pop();
int len = s.isEmpty()?i:i-s.peek()-1;
if(len>=height[tPeek])
max = Math.max(max, height[tPeek]);
}
}
return max*max;
}
//动态规划
//正方形都是由小正方形构成
//TC = O(m*n)
public int maxSquare(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
//对于i=0 || j=0, matrix为1的就是变成为1的小正方形
int max=0;
for(int i=0; i<m; i++){
if(matrix[i][0]==1)
max=1;
}
for(int i=0; i<n; i++){
if(matrix[0][i]==1)
max=1;
}
//状态转移方程
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
//对于(i,j)
//当(i-1,j-1)、(i,j-1)、(i-1,j)非0时,(i,j)可以构成正方形,且变成为前3点的最短边长
if(matrix[i-1][j-1]>0 && matrix[i-1][j]>0 && matrix[i][j-1]>0 && matrix[i][j]>0){
matrix[i][j] = Math.min(matrix[i-1][j-1], Math.min(matrix[i-1][j],matrix[i][j-1]))+1;
max = Math.max(max, matrix[i][j]);
}
}
}
return max*max;
}
}