题目描述:
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.
Credits:
要找到全为'1'的正方形最大面积,思路和64题的Minimum Path Sum很类似。从一个矩阵的左上方走到右下方,找到满足条件的所有正方形,求得最大的一个即可。
要计算全为'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;
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 01 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; //返回最大面积
}
};