leetcode221.最大正方形

一.题目描述

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

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

输入:matrix = [[“0”,“1”],[“1”,“0”]]
输出:1

输入:matrix = [[“0”]]
输出:0

提示:

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

二.题目解析

1.动态规划

public int maximalSquare(char[][] matrix) {
        /*动态规划
        状态:dp[i][j]表示以第i行j列元素为右下角的只包含1的最大正方形边长
        时间复杂度 O(height * width),空间复杂度O(height ∗ width)
        * */
        if(matrix == null || matrix.length == 0){
            return 0;
        }
        int height = matrix.length;
        int width = matrix[0].length;
        //dp数组全都初始化为0
        int[][] dp = new int[height][width];
        int cur,max = 0;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                cur = matrix[i][j] - '0';
                if(i == 0 || j == 0){
                    //如果是第一行或者第一列的元素,以它为右下角的只包含1的最大正方形
                    dp[i][j] = cur == 1 ? 1 : 0;
                }else if(cur == 1){
                    //如果当前元素为1,利用状态转移方程
                    //如果它的上方,左方和左上方为右下角的正方形的大小不一样,合起来就会缺了某个角落,所以要取这三个中最小的正方形边长+1
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1],dp[i - 1][j]),dp[i][j - 1]) + 1;
                }
                //如果当前元素是0,dp值为0,又因为初始化就是0,所以无需再处理
                //max不断保存更大的正方形边长
                max = Math.max(max,dp[i][j]);
            }
        }
        return max * max;
    }

在这里插入图片描述
2.状态压缩

public int maximalSquare1(char[][] matrix) {
        /*动态规划-状态压缩,由解法一可知每一列的计算只用到了上一列的结果,
        我们可以用一维数组来代替二维数组
        状态:dp[i]表示以某一列时的第i行元素为右下角的只包含1的最大正方形边长
        时间复杂度 O(height * width),空间复杂度O(height)
        * */
        if(matrix == null || matrix.length == 0){
            return 0;
        }
        int height = matrix.length;
        int width = matrix[0].length;
        //dp数组全都初始化为0
        int[] dp = new int[height];
        int cur,pre = 0,temp,max = 0;
        //注意i代表列数,j代表行数
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                cur = matrix[j][i] - '0';
                //第0列的计算不需要pre
                if(i == 0 || j == 0){
                    dp[j] = cur == 1 ? 1 : 0;
                }else{
                    //如果更新当前第j行的值,那么下一行的计算取左上角的值将被覆盖,所以需要先保存下
                    temp = dp[j];
                    //cur == 0时,一定要赋值为0,区别于二维数组无需赋值,因为一维dp数组会存在覆盖现象
                    dp[j] = cur == 1 ? Math.min(Math.min(pre, dp[j - 1]), dp[j]) + 1 : 0;
                    //更新pre
                    pre = temp;
                }
                max = Math.max(max,dp[j]);
            }
            //计算下一列时更新pre为dp数组第一个元素
            pre = dp[0];
        }
        return max * max;
    }

在这里插入图片描述
参考文章:
https://leetcode-cn.com/problems/maximal-square/solution/221-zui-da-zheng-fang-xing-tu-jie-shi-pin-yan-shi-/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值