221. 最大正方形

题目:

思路:

【0】本来一开始打算参考  剑指 Offer II 040. 矩阵中最大的矩形(85. 最大矩形)这篇,原因是十分相似,后来发现倒不如原生的操作会比较快。

【1】动态规划的思想,借助辅助空间将一些计算过的数值记录,减少遍历的次数

代码展示:

//时间43 ms 击败 10.95%
//内存50.8 MB 击败 94.83%
class Solution {
    public int maximalSquare(char[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        int[] height = new int[col];
        int max = 0;
        for (int i = 0; i < row; i++){
            updateHeights(height, matrix[i]);
            max = Math.max(max, largestSquareArea(height,matrix[i]));
        }
        return max;
    }

    private void updateHeights(int[] heights, char[] cells) {
        for (int j = 0; j < heights.length; j++) {
            heights[j] = cells[j] == '0' ? 0 : heights[j] + 1;
        }
    }

    private int largestSquareArea(int[] heights,char[] cells) {
        int len = heights.length;
        int max = 0;
        int k,value,wide = 0;

        for (int r = 0; r < len; r++) {
            // 如果该位置没有高则直接跳过
            if (heights[r] == 0) {
                wide = 0;
                continue;
            }
            // 因为正方形要求的是高和宽一致,所以短板取决于最小值
            wide++;
            value = Math.min(heights[r],wide);
            k = r;
            // 保证数组不会溢出
            while (--k >= 0 && (heights[k] >= value || heights[k]*heights[k] > max)) {}
            value = Math.min(value,r-k);
            max = Math.max(max, value*value);
        }
        return max;
    }
}


//时间7 ms 击败 32.45%
//内存53 MB 击败 33.12%
class Solution {
    public int maximalSquare(char[][] matrix) {
        int maxSide = 0;
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return maxSide;
        }
        int rows = matrix.length, columns = matrix[0].length;
        int[][] dp = new int[rows][columns];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        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]);
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
}

//时间5 ms 击败 95.11%
//内存52.8 MB 击败 51.59%
class Solution {
    private int min(int a,int b,int c){
        return Math.min(a,Math.min(b,c));
    }

    public int maximalSquare(char[][] matrix) {
        if(matrix == null) return 0;

        int m = matrix.length;
        int n = matrix[0].length;
        //dp[i][j] 以matrix[i][j]为右下角的 全是1的正方形的最大边长 可以以左上角为研究对象 但是麻烦一些
        int[][] dp = new int[m][n];

        //先计算第一行 第一列的值 
        for(int i = 0;i<m;i++){
            dp[i][0]  = matrix[i][0] - '0';
        }

        for(int j = 0;j<n;j++){
            dp[0][j] = matrix[0][j] - '0';
        }

        for(int i = 1;i<m;i++){
            for(int j = 1;j<n;j++){
                //没必要用递归计算
                if(matrix[i][j]=='0'){
                    continue;
                }
                dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1;
            }
        }

        int maxLength = 0;
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                maxLength = Math.max(maxLength,dp[i][j]);
            }
        }

        return maxLength*maxLength;
    }
}

 

posted @ 2023-07-10 12:25  忧愁的chafry  阅读(3)  评论(0编辑  收藏  举报