秋招-算法-最大正方形

90 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情 >>

一、题目描述 LeetCode - 221

在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。
示例 1:

image.png

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:4

示例 2:

image.png

输入:matrix = [["0","1"],["1","0"]]
输出:1

示例 3:

输入:matrix = [["0"]]
输出:0

注意:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 300
  • matrix[i][j] 为 '0' 或 '1'

二、解题思路

本题要求找到面积最大的正方形,可以考虑如何找到边长最长的正方形,这样就保证了面积最大。如何找到边长最长的正方形,可以使用动态规划来解决。

  • 创建一个与matrix一样大小的二维数组dp,其中dp[i][j]表示以matrix[i][j]为正方形右下角顶点,所能达到的最长边长的长度。
  • 在构造dp数组时,对于dp[i][j](i==0 || j==0)的情况下,如果matrix[i][j] == 1则dp[i][j] == 1,因为当dp[i][j](i==0 || j==0)为右下角顶点时,正方形无法再向外延伸。
  • 对于dp数组内部的元素,当matrix[i][j] == 1时dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])+1,既取与dp[i][j]相邻的三个点的最小值加一。因为其相邻的三个点在matrix中皆可构成正方形,当取最小值时就可以保证新的正方形小于等于相邻的三个点构成正方形的最小值,在加上matrix[i][j]这个点,就是新正方形的边长dp[i][j]。

三、代码

class Solution {
    public int maximalSquare(char[][] matrix) {
        int max = Integer.MIN_VALUE;
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];
        for (int i=0; i<row; i++){
            for (int j=0; j<col; 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;
                    }
                }
                max = Math.max(dp[i][j], max);
            }
        }
        return max * max;
    }
}

四、总结

本题使用动态规划解决,其时间复杂度为O(mn),空间复杂度为O(mn),其中m和n分别为matrix矩阵的行数和列数。