力扣221——最大正方形

这道题主要是利用动态规划,注意好边界条件,就能够解决。
<!-- more -->git

原题

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

示例:segmentfault

输入: 

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

输出: 4

原题url:https://leetcode-cn.com/probl...数组

解题

动态规划

这道题应该很快会让咱们想起使用动态规划,从左上角往右下角开始找。优化

假设咱们用一个二维数组dp,记录每个位置所能构成的最大正方形的边长(从左上角开始算)。位置(i, j)是 1,则其可能构成的正方形的边长是Min(dp(i - 1, j - 1), dp(i - 1, j), dp(i, j - 1)) + 1。看到这个,相信你也会理解了,每个位置所能构成的最大边长的条件,实际上是要求包围着它的左上角三个位置都是 1 才能够。url

一直递推回到最初点,也就意味着,第一行和第一列须要单独判断。spa

以前应该也有作过相似空间复杂度上的优化,咱们真的须要一个真正的二维数据dp来记录中间结果吗?其实咱们发现,当一个位置用过以后,这个位置自己的数字已经再也不重要,关键是该位置所能构成的最大正方形的边长,也就是咱们记录的中间结果。所以能够直接更新原数组上的数字。code

还有就是须要考虑一些特殊状况,好比只有一行或者一列的时候,咱们应该如何作。内存

接下来让咱们看看代码:leetcode

class Solution {
    public int maximalSquare(char[][] matrix) {
        // 高
        int height = matrix.length;
        if (height == 0) {
            return 0;
        }
        // 宽
        int width = matrix[0].length;

        // 检查第一行和第一列,是否有'1'
        int result = checkFirstRowAndCol(matrix, height, width);
        // 只有一行或一列,或者只有一个
        if (height == 1 || width == 1) {
            return result;
        }

        // result如今作为记录最大边的长度
        // 中间结果
        int temp;
        for (int i = 1; i < height; i++) {
            for (int j = 1; j < width; j++) {
                if (matrix[i][j] == '0') {
                    continue;
                }

                // 求出matrix[i - 1][j - 1]、matrix[i - 1][j]、matrix[i][j - 1]中的最小值
                temp = matrix[i - 1][j] < matrix[i][j - 1] ? matrix[i - 1][j] : matrix[i][j - 1];
                temp = temp < matrix[i - 1][j - 1] ? temp : matrix[i - 1][j - 1];
                // 更新当前节点的值
                matrix[i][j] = (char) (temp + 1);
                temp = temp + 1 - '0';

                if (result < temp) {
                    result = temp;
                }
            }
        }

        return result * result;
    }

    private int checkFirstRowAndCol(char[][] matrix, int height, int width) {
        // 检查第一列
        for (int i = 0; i < height; i++) {
            if (matrix[i][0] == '1') {
                return 1;
            }
        }

        // 检查第一行
        for (int i = 0; i < width; i++) {
            if (matrix[0][i] == '1') {
                return 1;
            }
        }

        return 0;
    }
}

提交OK,执行用时:5 ms,内存消耗:41.1 MB

上面的这个代码,我并非一次性就直接写出来的,也是在不断的提交中,发现有一些特殊状况没有考虑,幸运的是力扣会每次提交完以后会告诉我不知足时的输入的是什么样的,但这也会让我常常考虑不足,还须要努力。

总结

以上就是这道题目个人解答过程了,不知道你们是否理解了。这道题目利用动态规划其实就差很少了,但重点仍是在于特殊状况的判断,须要注意。

有兴趣的话能够访问个人博客或者关注个人公众号、头条号,说不定会有意外的惊喜。

https://death00.github.io/

公众号:健程之道