0008 最大正方形

最大正方形

编号:0008

试题来源:leetcode

文章目录

  • 试题描述
  • 示例
  • 算法
    • 暴力法
      • 思路分析
      • 代码实现
      • 复杂度
    • 动态规划
      • 思路分析
      • 代码实现
      • 复杂度分析

试题描述

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

示例

0008 最大正方形_第1张图片

算法

官方题解传送门

暴力法

思路分析

matrix二维数组进行遍历,当遍历到matrix[i][j] == 1的时候,以[i,j]作为可能正方形的左上角进行检验,每次检验一行和一列,例如,已经判断出正方形边长为tempLen,下一次就检验第i+tempLen行和j+tempLen列,如果全为 1 1 1,那么此次检验仍成功,继续。判断失败后,更新maxLen全局变量。

最后返回最大边长的平方,因为我们求解的是面积。

代码实现

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        int maxLen = 0, tempLen = 0;  //maxLen存储遇到的最大正方形边长,tempLen作为临时量,存储当前遇到的正方形边边长
        for(int i = 0; i<matrix.size();i++)   //两重循环遍历矩阵
        {
            for(int j = 0; j< matrix[i].size();j++)
            {
                if(matrix[i][j] == '1')   //等于1的话进行判断
                {
                    tempLen = 1;
                    while(tempLen + i < matrix.size() && tempLen + j < matrix[i].size())    //注意一定要在矩阵范围内寻找
                    {
                        bool flag = false;   //标定正常退出还是因为不满足退出
                        for(int m = 0; m < tempLen;m++)
                        {
                            if(matrix[i+m][j+tempLen] != '1' || matrix[i+tempLen][j+m] != '1')
                            {
                                flag = true;
                                break;
                            }
                                
                            if(matrix[i + tempLen][j+tempLen] != '1')
                            {
                                flag = true;
                                break;
                            }
                        }
                        if(!flag)   //正常退出tempLen+1,进行下一轮的判断
                            tempLen++;
                        else
                            break;
                    }
                    maxLen = max(maxLen,tempLen);  //更新maxLen
                }
            }
        }
        return maxLen * maxLen;        //返回面积
    }
};

下面是官方题解

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }  //判断一下矩形的形状
        int maxSide = 0;//最大边长
        int rows = matrix.size(), columns = matrix[0].size();//取行数和列数
        for (int i = 0; i < rows; i++) {    //二重循环遍历
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    // 遇到一个 1 作为正方形的左上角
                    maxSide = max(maxSide, 1);
                    // 计算可能的最大正方形边长
                    int currentMaxSide = min(rows - i, columns - j);
                    for (int k = 1; k < currentMaxSide; k++) {
                        // 判断新增的一行一列是否均为 1
                        bool flag = true;
                        if (matrix[i + k][j + k] == '0') {
                            break;
                        }
                        for (int m = 0; m < k; m++) {
                            if (matrix[i + k][j + m] == '0' || matrix[i + m][j + k] == '0') {
                                flag = false;
                                break;
                            }
                        }
                        if (flag) {
                            maxSide = max(maxSide, k + 1);
                        } else {
                            break;
                        }
                    }
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
};

基本没啥差别,和我写的

复杂度

  • 时间复杂度: O ( m ∗ n ∗ m i n ( m , n ) 2 ) O(m*n*min(m,n)^2) O(mnmin(m,n)2);遍历整个矩阵的时间复杂度为 O ( m ∗ n ) O(m*n) O(mn),对于正方形,遍历的事件复杂度为 O ( m i n ( m , n ) 2 ) O(min(m,n)^2) O(min(m,n)2)
  • 空间复杂度: O ( 1 ) O(1) O(1),整个过程中使用的空间复杂度是常数

动态规划

思路分析

d p ( i , j ) dp(i,j) dp(i,j)表示以 ( i , j ) (i,j) (i,j)为右下角,且只包含 1 1 1的正方形的边长最大值。

如果matrix[i][j]==0,那么显然不可能在一个只含有 1 1 1的正方形中,因此 d p ( i , j ) = 0 dp(i,j)=0 dp(i,j)=0

如果matrix[i][j]==1,那么显然dp[i][j]=min(dp(i-1,j),dp(i-1,j-1),dp(i,j-1))+1

得出状态转移方程

代码实现

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }  //判断矩形的形状
        int maxSide = 0;    //正方形的最大边长
        int rows = matrix.size(), columns = matrix[0].size();   //判断一下行,列
        vector<vector<int>> dp(rows, vector<int>(columns));     //创建一个dp矩形
        for (int i = 0; i < rows; i++) {     //二重循环遍历,动态规划
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    }
                    maxSide = max(maxSide, dp[i][j]);
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
};

复杂度分析

  • 时间复杂度: O ( m n ) O(mn) O(mn),整个过程中只进行两层遍历
  • 空间复杂度: O ( m n ) O(mn) O(mn),创建了一个和原始矩阵大小相同的矩阵 d p dp dp

你可能感兴趣的:(每天一道算法题)