T221 最大正方形

case1思想:遍历整个matrix,分别以(i,j)作为起点(作为构成的矩阵左上角元素)构建正方形(重点是如何构造这个正方形!!!),统计每次构造成的正方形的边长,选取其中最大的那个。

class Solution {
    public int maximalSquare(char[][] matrix) {
    int rows = matrix.length;
    if(rows==0) return 0;
    int cols = matrix[0].length;
    //记录最大边长
    int maxLen = 0;
    //记录当前边长
    int edgLen = 0;
    //flag用于记录当前行遍历的数据是否全为'1'
    boolean flag;
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            //每次以matrix[i][j]作为起点时重新初始化edgLen和flag
            //且只有当遍历到的数据均为'1'时才以其作为所构造正方形的左上角元素构造正方形
            if(matrix[i][j]=='1'){
                edgLen = 1;
                flag = true;
                //进行扩张,每次在原正方形的基础上再额外扩展1行和1列且.因为现在的起点左边是从(i,j)开始而不是(0,0)开始了,所有说现在扩张后的行(列)的下标应为i(j)+edglen(每次自增1)
            //当能够再次扩展且再次扩展的那一行那一列还在matrix内部时再次尝试将正方形扩展一行一列   
           while(i+edgLen<rows&&j+edgLen<cols&&flag){
                //判断新扩展的那一行的数据是否均为'1'
                for(int r=i;r<=i+edgLen;r++){
                    if(matrix[r][j+edgLen]=='0'){
                        flag = false;
                        break;
                    }
                }
                 //判断新扩展的那一列的数据是否均为'1'
                 for(int c=j;c<=j+edgLen;c++){
                    if(matrix[i+edgLen][c]=='0'){
                        flag = false;
                        break;
                    }
                }          
                //若所扩展的数据均为1,满足要求,扩展成功,边长自增1
                if(flag){
                    edgLen++;
                }
            }
             //以点(i,j)为起点的正方形扩展结束后,更新最大边长
                if(maxLen<edgLen){
                    maxLen = edgLen;
                }
            }
        }
    }
    return maxLen*maxLen;
    }
}

case2:利用DP思想
DP思想:
1.dp[i][j]表示以matrix[i-1][j-1]作为右下角元素构成的正方形的边长(这样是为了可以方便matrix中的所有数据均能利用下面的DP公式进行求解)
2.dp[i][j] = min(dp[i-1][j],dp[i-1][j-1],dp[i][j-1])+1
也就是以matrix[i][j]作为右下角元素构成的正方形的边长=分别以matrix[i][j]这个元素的左边,左上,上边的那个元素为右上角构成的正方形的边长的最小值+1
3.怎么理解这个DP公式:
因为我们这里设定的dp[i][j]表示以matrix[i][j]作为右下角元素(!!!)构成的正方形的边长
所以要以matrix[i][j]作为右下角元素(!!!)构成的正方形:它只能是以matrix[i][j]这个元素的左边,左上,上边的那个元素为右上角构成的正方形中最短的边所构成的正方形再分别扩展一列,扩展一行所形成的正方形。那么问题就来了,如何进行扩展能保证扩展后的正方形仍然满足要求:该正方形全部由’1’构成。明显(观察图)发现只有以那三个中最短的边所围成的正方形为基准然后分别再分别扩展一列,扩展一行所形成的正方形才满足要求,其他两个都不能保证
4.每次求出一个边长时就更新最大边长,最后要求的正方形的最大面积即为最大边长*最大边长
在这里插入图片描述

class Solution {
    public int maximalSquare(char[][] matrix) {
     int rows = matrix.length;
     if(rows==0) return 0;
     int cols = matrix[0].length;
     int maxEdgLength = 0;
     //这里多出来的一行一列是为了方便初始化matrix第0行和第0列的数据(也就是能为了让他们也能借助dp公式进行求解)
     int[][]dp = new int[rows+1][cols+1];
     for(int i=1;i<=rows;i++){
         for(int j=1;j<=cols;j++){
             //当matrix[i-1][j-1]=='1'时才能以其作为右下角元素构成正方形,才能去求对应正方形的边长
             if(matrix[i-1][j-1]=='1'){
                 dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i-1][j-1]),dp[i][j-1])+1;
                 if(maxEdgLength<dp[i][j]){
                     maxEdgLength = dp[i][j]; 
                 }
             }
         }
     }
     return maxEdgLength*maxEdgLength;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值