• leetcode 221. Maximal Square


    Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.

    Example:

    Input: 
    
    1 0 1 0 0
    1 0 1 1 1
    1 1 1 1 1
    1 0 0 1 0
    
    Output: 4

    题目大意:给定一个只包含0和1的二维二值矩阵,找到只包含1的最大正方形,并返回它的面积。

    思路一:用一个临时变量a记录最大正方形的边长,遍历矩阵的每一个点(i,j), 另一个临时变量b记录以点(i,j)为左上角点的符合条件(全为1)的正方形的边长,如果b大于a,则更新a。

    C++代码:

     1 int maximalSquare(vector<vector<char>>& matrix) {
     2         int rows = matrix.size(), colums = rows > 0 ? matrix[0].size() : 0;
     3         int maxsqlen = 0;
     4         for (int i = 0; i < rows;  ++i) {
     5             for (int j = 0; j < colums; ++j) {
     6                 //只有(i,j)为1,才有可能组成符合条件的正方形
     7                 if (matrix[i][j] == '1') {
     8                     int sqlen = 1; //从以(i,j)为左上角点的边长为sqlen = 1的正方形开始判断
     9                     bool flag = true; //记录边长为sqlen的正方形是否符合条件的
    10                     //判断以(i,j)为左上角点的边长为sqlen+1的正方形是否在matrix中,并且判断长为sqlen的正方形是否是符合条件的,如果不符合,那么同以(i,j)为左上角点,边长sqlen+1的正方形必然是不符合条件的
    11                     while (i + sqlen < rows && j + sqlen < colums && flag) {
    12                         //判断新的正方形的最后一行是否符合条件
    13                         for (int k = j; k <= sqlen + j; ++k) {
    14                             if (matrix[i + sqlen][k] == '0') {
    15                                 flag = false;
    16                                 break;
    17                             }
    18                         }
    19                         //判断新的正方形的最后一列是否符合条件
    20                         for (int k = i; k <= sqlen + i; ++k) {
    21                             if (matrix[k][j + sqlen] == '0') {
    22                                 flag = false;
    23                                 break;
    24                             }
    25                         }
    26                         //前两个循环结束判断,如果flag=ture,说明原来边长增长1的正方形仍然是符合条件的正方形。
    27                         if (flag)
    28                             sqlen++;
    29                     }
    30                     //结束前面循环后,sqlen为以(i,j)为左上角点的符合条件的最大正方形的边长,如果sqlen大于当前最大边长,则更新
    31                     if (maxsqlen < sqlen) {
    32                         maxsqlen = sqlen;
    33                     }
    34                 }
    35                 
    36             }
    37         }
    38         return maxsqlen * maxsqlen;
    39     }

    时间复杂度:$O((mn^)2)$

    空间复杂度:$O(1)$


    也可以考虑前序和,新开辟一个二维数组dp,大小和原矩阵相同,dp[i][j]的值表示以原矩阵(0,0)为左上角点,(i,j)为右下角点组成的矩形的和。

    dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + matrix[i][j]

    记录完之后,当计算以(i,j)为左上角点长为sqlen时的正方形的和便可以直接得到,判断这个正方形是不是符合条件的,只要判断和是不是等于sqlen * sqlen.

     1 int maximalSquare(vector<vector<char>>& matrix) {
     2         int rows = matrix.size(), cols = rows > 0 ? matrix[0].size() : 0;
     3         int maxsqlen = 0;
     4         vector<vector<int> > dp(rows + 1, vector<int>(cols + 1, 0));
     5         for (int i = 1; i <= rows; ++i) {
     6             for (int j = 1; j <= cols; ++j) {
     7                 dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + (matrix[i - 1][j - 1] - '0');
     8             }
     9         }
    10         for (int i = 0; i < rows; ++i) {
    11             for (int j = 0; j < cols; ++j) {
    12                 for (int k = 0; k < min(rows - i, cols - j); ++k) {
    13                     int temp = dp[i + k + 1][j + k + 1] - dp[i][j + k + 1] - dp[i + k + 1][j] + dp[i][j];
    14                     if (temp == (k + 1) * (k + 1)) {
    15                         maxsqlen = max(maxsqlen, temp);
    16                     } else {
    17                         break;
    18                     }
    19                 }
    20             }
    21         }
    22         return maxsqlen;
    23     }

    思路二:(动态规划)

    建立一个二维 dp 数组,其中 dp[i][j] 表示到达 (i, j) 位置所能组成的最大正方形的边长。我们首先来考虑边界情况,也就是当i或j为0的情况,那么在首行或者首列中,必定有一个方向长度为1,那么就无法组成长度超过1的正方形,最多能组成长度为1的正方形,条件是当前位置为1。对于任意一点 dp[i][j],由于该点是正方形的右下角,所以该点的右边,下边,右下边都不用考虑,关心的就是左边,上边,和左上边。这三个位置的dp值 suppose 都应该算好的,还有就是要知道一点,只有当前 (i, j) 位置为1,dp[i][j] 才有可能大于0,否则 dp[i][j] 一定为0。当 (i, j) 位置为1,此时要看 dp[i-1][j-1], dp[i][j-1],和 dp[i-1][j] 这三个位置,我们找其中最小的值,并加上1,就是 dp[i][j] 的当前值了。

     1 int maximalSquare(vector<vector<char>>& matrix) {
     2         int rows = matrix.size(), cols = rows > 0 ? matrix[0].size() : 0;
     3         int maxsqlen = 0;
     4         vector<vector<int> > dp(rows + 1, vector<int>(cols + 1, 0));
     5         for (int i = 1; i <= rows; ++i) {
     6             for (int j = 1; j <= cols; ++j) {
     7                 if (matrix[i - 1][j - 1] == '1') {
     8                     dp[i][j] = min(min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i][j - 1]) + 1;  
     9                 }
    10                 maxsqlen = max(maxsqlen, dp[i][j]);
    11             }
    12         }
    13         return maxsqlen * maxsqlen;
    14     }
  • 相关阅读:
    nginx虚拟主机解决企业内外网访问
    oarcle mysql 字段的区别和互换
    大话“扁平化设计”
    使用OGR创建弧形图形
    socket连接和http连接的区别
    nginx tomcat 配置集群负载
    GDAL工具使用示例(一)
    无法解析或打开软件包的列表或是状态文件 解决方案
    程序员们必看,不要让光环效应毁了你辛辛苦苦做的软件
    [spring]Bean注入——在XML中配置
  • 原文地址:https://www.cnblogs.com/qinduanyinghua/p/12802959.html
Copyright © 2020-2023  润新知