【字节专题】leetcode 221. 最大正方形

最大正方形算法解析
本文详细解析了在由0和1组成的二维矩阵中寻找最大正方形的问题,通过动态规划的方法,利用一个同样维数的dp矩阵,实现了高效求解最大正方形边长的过程。

221. 最大正方形

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

示例:
输入: 
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

输出: 4

不需要额外空间 直接原地dp

写得有点丑,没有大佬们的好看。

第一个for遍历1~max_edge,也就是最长的边。
第二三个for,判断matrix[i][j]=='1' && matrix[i-1][j]=='1' && matrix[i][j-1]=='1' && matrix[i-1][j-1]=='1',也就是当前位置,以及它左上角的位置,以及左边的位置,上边的位置都为1,说明可以组成边长为当前len的正方形。注意len为1时只要找到一个就可以break了,len>1时,比如len==2,要遍历所有可能的位置,更新matrix[i][j],这个是接下来len++后判断需要使用的。最后可以做的剪枝,若在当前len下不能更新找到更大的正方形,则接下来更不可能找到了,直接break。
【注意】:这个matrix在不同的len下含义的不同的喔。

public static int maximalSquare(char[][] matrix) {
    if (matrix==null || matrix.length==0 || matrix[0]==null || matrix[0].length==0)    return 0;
    int row = matrix.length;
    int col = matrix[0].length;

    int max_edge = Math.min(row, col);
    int max_area = 0;
    for (int len = 1;len<=max_edge;len++){
        boolean flag = false;
        for (int i = row-1;i>=len-1;i--){
            for (int j = col-1;j>=len-1;j--){
                if (matrix[i][j]=='1' && len==1) {
                    max_area = Math.max(max_area, len * len);
                    flag = true;
                    break;
                }
                if (len!=1) {
                    if (matrix[i][j]=='1' && matrix[i-1][j]=='1' &&
                            matrix[i][j-1]=='1' && matrix[i-1][j-1]=='1'){
                        flag=true;
                        max_area = Math.max(max_area, len*len);
                    }else {
                        matrix[i][j]=0;
                    }
                }
            }
            if (flag && len==1)   break;
        }
        if (flag==false)
            break;
    }
    return max_area;
}

动态规划

我们用一个例子来解释这个方法:

0 1 1 1 0
1 1 1 1 1
0 1 1 1 1
0 1 1 1 1
0 0 1 1 1
  1. 我们用 0 初始化另一个矩阵 dp,维数和原始矩阵维数相同;
  2. dp(i,j) 表示的是由 1 组成的最大正方形的边长;
  3. 从 (0,0) 开始,对原始矩阵中的每一个 1,我们将当前元素的值更新为
    dp(i, j)=min(dp(i−1, j), dp(i−1, j−1), dp(i, j−1))+1
  4. 我们还用一个变量记录当前出现的最大边长,这样遍历一次,找到最大的正方形边长 maxsqlen,那么结果就是 maxsqlen^2。

可以通过下面的图来理解该工作原理:
在这里插入图片描述

public class Solution {
    public int maximalSquare(char[][] matrix) {
        int rows = matrix.length, cols = rows > 0 ? matrix[0].length : 0;
        int[][] dp = new int[rows + 1][cols + 1];
        int maxsqlen = 0;
        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                if (matrix[i-1][j-1] == '1'){
                    dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
                    maxsqlen = Math.max(maxsqlen, dp[i][j]);
                }
            }
        }
        return maxsqlen * maxsqlen;
    }
}

复杂度分析

  • 时间复杂度:O(mn)O(mn)。
  • 空间复杂度:O(mn)O(mn),用了一个大小相同的矩阵 dp。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值