题目链接:​​Maximal Square​

题目大意:给定一个零一矩阵,要求你找到里面最大的全1正方形(下面直接用矩阵表示)

题目思路:一个简单DP,对于一个矩阵,我们需要考虑这样一个问题,这个矩阵是全1矩阵,如果这个1可以往下接着延申,那么这个全1矩阵就不是最优的,所以我们需要考虑对于某个1,他能得到的最优矩阵,那么一定是这个1是当前最优矩阵的右下角,我们可以用dp[i][j]表示以这个元素为右下角的最优矩阵的边长,那么我们需要一个合理的转移方程,首先,如果该元素是0,那么直接是零了,不用讨论,只有在当前元素为1的时候才有可能出现矩阵叠加,我们考虑这样一个情况,如果这个元素是某个矩阵的右下角,那么他的上面,左边,以及斜上的某个矩阵,一定是1,那么我们去考虑他的边长,他的边长可以是他上面一些连续的1元素以及他左边的一些连续1,那么这个过程其实也就是Min(dp[i-1][j],dp[i][j-1])+1,因为正方形边长肯定是最小的一个,那么这个边长我们可以初步确定了,但是,我们这里只确定了一件事,这样的一个矩阵的最右边一列和最下边一行全是1,其他元素还没有确定,这个可以用dp[i-1][j-1]确定,这个实际上就是剩下的一些元素是否为1,如果这个小了的话,也不能够扩展到之前定的边长,所以还需要去对比这个元素的最小值,那么转移方程也就定了,也即dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1。此外,这个空间也可以优化,我们每次只会最多考虑到最多他的上一层元素,所以可以用dp[j]直接表示当前访问到的行的更新值,用prev表示之前的dp[i-j][j-1],每次更新的时候使用dp[j] = min(prev,dp[j-1],dp[j])+1,prev = dp[j] (没更新之前的dp[j]即可),代码也很好写,不过我没写,只写了这个二维的dp做法

时间复杂度&&空间复杂度:O(nm)&&O(nm)

class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int len1 = matrix.size();
if(len1 == 0) return 0;
int len2 = matrix[0].size();
vector<vector<int>>dp(len1,vector<int>(len2));
int maxx = 0;
for(int i = 0;i < len1;i++) dp[i][0] = matrix[i][0]-'0',maxx = max(maxx,dp[i][0]);
for(int j = 0;j < len2;j++) dp[0][j] = matrix[0][j]-'0',maxx = max(maxx,dp[0][j]);
for(int i = 1;i < len1;i++){
for(int j = 1;j < len2;j++){
if(matrix[i][j] == '1') dp[i][j] = min(min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
else dp[i][j] = 0;
maxx = max(maxx,dp[i][j]);
}
}
return maxx*maxx;
}
};