给定一个由 '0' 和 '1' 组成的2维矩阵,返回该矩阵中最大的由 '1' 组成的正方形的面积。输入的矩阵是字符形式而非数字形式。
数据范围:矩阵的长宽满足 ,矩阵中的元素属于 {'1','0'}
进阶:空间复杂度 , 时间复杂度
[[1,0,1,0,0],[1,0,1,1,1],[1,1,1,1,1],[1,0,0,1,0]]
4
[[1,0,0],[0,0,0],[0,0,0]]
1
public int solve (char[][] matrix) { if(matrix == null || matrix.length == 0) return 0; Stack<Integer> stack = new Stack<>(); int maxRes = 0; int m = matrix.length, n = matrix[0].length; int[] arr = new int[n+2]; for(int i = 0; i < m; i++){ stack.push(0); for(int j = 1; j < n+2; j++){ if(j < n+1){ if(matrix[i][j-1] == '1'){ arr[j]++; }else{ arr[j] = 0; } } while(!stack.isEmpty() && arr[stack.peek()] > arr[j]){ int length = Math.min(arr[stack.pop()], j-stack.peek()-1); maxRes = Math.max(maxRes, length); } stack.push(j); } while(!stack.isEmpty()) stack.pop(); } return maxRes*maxRes; }
public int solve (char[][] matrix) { if(matrix == null || matrix.length == 0) return 0; int m = matrix.length, n = matrix[0].length; int[][] dp = new int[m+1][n+1]; int max = 0; for(int i = 1; i < m+1; i++){ for(int j = 1; j < n+1; j++){ if(matrix[i-1][j-1] == '1'){ dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j], dp[i][j-1])) + 1; max = Math.max(max, dp[i][j]); } } } return max*max; }
public class Solution { public int solve (char[][] matrix) { int m = matrix.length, n = matrix[0].length; int[][] dp = new int[m+1][n+1]; int max = Math.max(0, matrix[0][0] - 48); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (matrix[i-1][j-1] == '1') { dp[i][j] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1; max = Math.max(max, dp[i][j]); } } } return max * max; } }
public int solve (char[][] matrix) { //以[i,j]位置为右下角的正方形取决于它所在的左、上、左上位置所能组成的最大正方形的周长。 //如果[i,j]=0,那么就不可能组成正方形 int m=matrix.length; int n=matrix[0].length; int [][]dp=new int[m][n]; int side=0; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(matrix[i][j]=='0') dp[i][j]=0; else{ if(i==0||j==0) dp[i][j]=1;//边界上只能凑成边长为1的正方形 else dp[i][j]=Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i][j-1]))+1; } side=Math.max(side,dp[i][j]); } } return side*side; }
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ public int solve (char[][] matrix) { // write code here int area = 0; int rows = matrix.length; int cols = matrix[0].length; int[][] dp = new int[rows+1][cols+1]; for(int i=1; i<=rows; i++){ for(int j=1; j<=cols; j++){ if(matrix[i-1][j-1] == '1'){ dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i][j-1], dp[i-1][j])) +1; area = Math.max(area, dp[i][j]*dp[i][j]); } } } return area; } }动态规划算法
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ //检测过程 如果在方块内部有任意一个值为0 则不构成方块 public boolean checkQ(char[][] a, int i, int j, int k){ int m = a.length; int n = a[0].length; for(int p=0;p<k;p++){ for(int q=0;q<k;q++){ if(a[i+p][j+q] == 0 || a[i+p][j+q] == '0'){ return false; } } } return true; } public int solve (char[][] matrix) { // write code here int m = matrix.length; int n = matrix[0].length; char[][] a = matrix; char[][] temp = new char[n][m]; if(m > n){ //为了方便 统一将方块转换为列大于行,对二维数组进行一个翻转 for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ temp[j][i] = matrix[i][j]; } } a = temp; } //开始从最大的方块检测 for(int k=m;k>0;k--){ //移动方块列的位置 for(int i=0;i<m-k+1;i++){ //移动方块行的位置 for(int j=0;j<n-k+1;j++){ //检测 boolean flag = checkQ(a, i, j, k); if(flag == true){ return k*k; } } } } return 1; } }
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ public int solve (char[][] matrix) { // write code here if(matrix == null){return 0;} int m = matrix.length; int n = matrix[0].length; int res = 0; int[][] dp = new int[m + 1][n + 1]; for(int i = 1; i <= m; ++i){ for(int j = 1; j <= n; ++j){ if(matrix[i - 1][j - 1] == '1'){ dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; res = Math.max(res, dp[i][j]); } } } return res * res; } }
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ public int solve (char[][] matrix) { // write code here if (matrix.length == 1 && matrix[0].length == 1) { return matrix[0][0] - 48; } if (matrix.length == 0) { return 0; } int ans = Integer.MIN_VALUE; int m = matrix.length, n = matrix[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0 || j == 0) { continue; } if (matrix[i][j] == '1') { int temp = Math.min(matrix[i][j - 1] - 48, matrix[i - 1][j] - 48); temp = Math.min(temp, matrix[i - 1][j - 1] - 48) + 1; matrix[i][j] = (char)(48 + temp); if (ans < temp) { ans = temp; } } } } return ans * ans; } }
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ public int solve (char[][] matrix) { // write code here if(matrix.length==0||matrix[0].length==0) { return 0; } int m = matrix.length; int n = matrix[0].length; int max = 0; int[][] dp = new int[m][n]; for (int i = 0; i < m; i++) { //将字符数组变为整形数组 for (int j = 0; j < n ; j++) { dp[i][j] = matrix[i][j]-'0'; if (dp[i][j] == 1) { max = 1; } } } for(int i = 1;i<m; i++){ for(int j = 1;j<n; j++){ if(matrix[i][j]=='1'){ // (i, j) 为正方形右下顶点,对比小单位正方形左下顶点(i, j-1), 左上顶点(i-1, j-1),右上顶点(i-1, j)的最小值(正方形边) dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j], dp[i][j-1])) + 1; max = Math.max(dp[i][j], max); } } } return max*max; } }
import java.util.*; public class Solution { /** * 最大正方形 * @param matrix char字符型二维数组 * @return int整型 */ public int solve (char[][] matrix) { // write code here int [][]dp = new int[matrix.length][matrix[0].length]; int bc = 0; dp[0][0]=0; for(int i=0;i<dp.length;i++){ dp[i][0]=matrix[i][0]-'0'; } for(int j=0;j<dp[0].length;j++){ dp[0][j]=matrix[0][j]-'0'; } for(int i=1;i<dp.length;i++){ for(int j=1;j<dp[0].length;j++){ if(matrix[i][j]=='0'){ dp[i][j]=0; }else{ int up = dp[i-1][j]; int left = dp[i][j-1]; int ul = dp[i-1][j-1]; if(up==left && up==ul){ dp[i][j]=up+1; }else{ int m = Math.min(up,Math.min(left,ul)); dp[i][j]=m+1; } } } } for(int i=0;i<dp.length;i++){ for(int j=0;j<dp[0].length;j++){ bc = Math.max(bc,dp[i][j]); } } int area = bc*bc; return area; } }前排提示:这道题有个很坑的地方,java输入的matrix是字符型。自测的时候算出来面积两千多,一直不知道啥问题,一看函数参数列表......
用dp[i][j]表示以matrix[i][j]为右下角的全为1组成的最大正方形的边长,则:
1. 若matrix[i][j] == 0, 则dp[i][j] = 0
2. 若matrix[i][j] == 1, 则dp[i][j] = min{dp[i-1][j], dp[i][j-1], dp[i-1][j-1]} + 1
原因可以看下面这张图: