LeetCode 221.最大正方形

111 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目:在一个由01字符组成的二维矩阵内,找到只包含1的最大正方形,并且返回其面积。

例如:输入matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]输出为4。

解题思路

本题是经典的动态规划问题,求一个正方形的最大面积就是求正方形的最大边长为多少,之后平方即可。我们可以想象一下,我们遍历数组,当遍历到字符0的时候则跳过,当遍历到字符1的时候,这个字符就可以作为正方形的一部分,如果我们将这个字符作为正方形的左上角,那么我们就需要向下和向右分别扩增一行,并且保证由向下和向右对应的部分也为字符1,代码较为复杂。

换个思路想一下,我们是否可以将此字符作为正方形的右下角的一部分,这样就容易很多,因为确定了一个角,那么就可以通过判断这个角的左边上边以及斜上角来判断这个正方形的最大边长,如果上述三个值全是字符1则正方形的边长在此基础上加一。可得动态规划转移方程为:

dp[i][j]=min(dp[i1][j],dp[i][j1],dp[i1][j1])+1dp[i][j] = min(dp[i-1][j], dp[i][j-1],dp[i-1][j-1])+1

动态转移方程一般需要初始化,在本题则可以直接计算,当序号为边界的时候,如果字符为1则动态转移方程也为1,否则为0,可得如下代码:

public int maximalSquare(char[][] matrix) {
        int[][] dp = new int[matrix.length][matrix[0].length];
        int maxLen = 0;
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[0].length;j++){
                if(matrix[i][j]=='1') {
                    if(i==0||j==0){
                        dp[i][j] = 1;
                    }else {
                        dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1]))+1;
                    }
                    maxLen = Math.max(maxLen, dp[i][j]);
                }
            }
        }
        return maxLen*maxLen;
    }

上述代码的时间复杂度和空间复杂度都为O(n+m)O(n+m),其中mn分别代表数组的长度和宽度。