LeetCode 221 最大正方形(中等 动态规划)

最大正方形

1.题目

你在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。
示例1:
LeetCode 221 最大正方形(中等 动态规划)_第1张图片
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:4

示例2:
LeetCode 221 最大正方形(中等 动态规划)_第2张图片输入:matrix = [[“0”,“1”],[“1”,“0”]]
输出:1
提示:m == matrix.length
n == matrix[i].length
1 <= m, n <= 300
matrix[i][j] 为 ‘0’ 或 ‘1’

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximal-square
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.题解

        题目要求计算最大正方形的面积,考虑到题目中给出的矩阵的范围可以尝试使用三重循环来计算最大的面积,具体方法是首先采用预处理的方式计算出一个结果即num[i][j], 该结果表示以i和j结尾的矩阵中1的个数,然后循环遍历每一个点,对于该点而言遍历正方形的长度L,计算长度为L的情况下以i和j为终点的正方形中1的个数是否为L * L,即

if((num[i][j] - num[i - L][j] - num[i][j - L] + num[i - L][j - L) == L * L])  maxArea = Math.max(maxArea, L * L);

上面这个公式就可以计算最大的面积,时间复杂度为(300 * 300 * 300),可以尝试这么做

  • 代码如下

class Solution {
    public int maximalSquare(char[][] matrix) {
        int n = matrix.length, m = matrix[0].length, maxArea = 0;
        int[][] num = new int[n + 1][m + 1];
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(i == 0 && j == 0) {
                    num[i][j] = matrix[i - 1][j - 1] - '0';
                }
                else if(i == 0) num[i][j] = num[i][j - 1] + matrix[i - 1][j - 1] - '0';
                else if(j == 0) num[i][j] = num[i - 1][j] + matrix[i - 1][j - 1] - '0';
                else num[i][j] = num[i - 1][j] + num[i][j - 1] - num[i - 1][j -1] + matrix[i - 1][j - 1] - '0';
                if(num[i][j] > 0) maxArea = 1;
            }
        }
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                for(int L = 1; L <= Math.min(i, j); L++){
                    if((num[i][j] - num[i - L][j] - num[i][j - L] + num[i - L][j - L]) == L * L)
                        maxArea = Math.max(maxArea, L * L);
                }
            }
        }
        return maxArea;
    }
}

该方法可以通过,但是考虑到时间复杂度太高,还是考虑用动态规划,有dp[i][j],其中i和j分别表示横纵坐标,而dp[i][j] 则表示i,j结尾的最大正方形,需要考虑的是怎么得到该结果,由于覆盖的问题,可以发现dp[i][j]由三个部分影响,dp[i - 1][j], dp[i][j - 1], dp[i - 1][j -1],而dp[i][j]需要取到另外三个结果中的最小值,并且当前这个点为1,才能计算出最大正方形,那么就可以得到动态转移公式:

dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;

由此就能计算出由每一个点为结尾的最大正方形的边长,只需要在这个计算的过程中维护一个最大边长的过程,最后返回面积即可,并且复杂度降为了(300 * 300)效率提高了很多。

  • 代码如下
class Solution {
    public int maximalSquare(char[][] matrix) {
        int n = matrix.length, m = matrix[0].length, maxArea = 0;
        int[][] dp = new int[n][m];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                dp[i][j] = matrix[i][j] - '0';
                if(maxArea == 0 && dp[i][j] == 1) maxArea = 1;
            }
        }
        for(int i = 1; i < n; i++){
            for(int j = 1; j < m; j++){
                if(dp[i][j] == 1){
                    dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i - 1][j - 1], dp[i][j - 1]));
                    dp[i][j] += 1;
                    maxArea = Math.max(maxArea, dp[i][j]);
                }
            }
        }
        return maxArea * maxArea;
    }
}

你可能感兴趣的:(LeetCode,leetcode)