Maximal Square - LeetCode 221

题目描述:

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

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.
Credits:

Special thanks to @Freezen for adding this problem and creating all test cases.

Hide Tags Dynamic Programming

分析:
要找到全为'1'的正方形最大面积,思路和64题的Minimum Path Sum很类似。从一个矩阵的左上方走到右下方,找到满足条件的所有正方形,求得最大的一个即可。

这样可以用一个二维数组dp[][]来存放计算过程中临时最大值。其中dp[i][j]表示以matrix[i][j]为右下角端点的全为'1'的最大的方阵的边长,那么最后求出求出最大的边长max,即可得到最大面积max * max。

那么递推公式是怎样的呢?最暴力的方法就是动笔在纸上挨着画几个例子,归纳法找规律:

首先,但看第0行和第0列,由于没有三个前向邻居(每个元素的左边、上变和左上的元素),而体重要求的是方阵的面积,因此对于dp第0行和第0列,直接等于matrix中的字符对应的数字即可。

然后问题来了,如何更新dp[i][j](i>0 && j>0)?
要计算全为'1'的方阵,那么
    当matrix[i][j]为'0'时,以当前节点为右下角节点时,最大的全为'1'的方阵不存在,此时dp[i][j] = 0;
    当matrix[i][j]为'1'时,如果当前节点位置对应的dp中节点左上相邻的三个元素均均为r,则dp[i][j] = r+1
          如果当前节点位置对应的dp中节点左上相邻的三个元素不相等,那么dp[i][j] = min(三个前向邻居)+1
          合并起来就是dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j]) + 1;
 

以下是C++实现代码:

/**///12ms*/
class Solution {
public:
    int min(int a,int b,int c){ //返回三个数中最小值
        int tmp = a < b ? a:b;
        return (tmp < c) ? tmp : c;
    }
    int maximalSquare(vector<vector<char>>& matrix) {
        int m = matrix.size();
        if(m == 0) //为空,则返回0
            return 0;
        int n = matrix[0].size();

        vector<vector<int>> dp(m,vector<int>(n,0)); //临时二维数组
        int max = 0; //最大边长变量
        for(int i = 0; i < m; i++){ //初始化第0列
            if(matrix[i][0] == '0' )
                 dp[i][0] = 0;
            else
                 dp[i][0] = 1;

            if(max < dp[i][0]) //同时更新最大边长
                max = dp[i][0];
        }
   
        for(int j = 0; j < n; j++){ //初始化第0行
            if(matrix[0][j] == '0' )
                 dp[0][j] = 0;
            else
                 dp[0][j] = 1;

            if(max < dp[0][j]) //同时更新最大边长
                max = dp[0][j];
        }

        for(int i = 1; i < m; i++){ //计算非0行和非0列元素作为最右下角元素的全为'1'的最大边长
            for(int j = 1; j < n; j++){
                if(matrix[i][j] == '0' ) //matrix[i][j] == 0,那么该位置对应的最大边长为0
                    dp[i][j] = 0;
                else{ matrix[i][j]==1的时候,用递推公式迭代
                    dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j]) + 1;

                    if(max < dp[i][j])   //更新最大边长 
                        max = dp[i][j];
                }
            }
        }
        return max * max; //返回最大面积
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值