题目
在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
示例:
输入:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
输出: 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximal-square
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
动态规划思想:将一个问题划分为N个子问题,逐个解析子问题,前一个子问题的输出作为下一个子问题的输入,直到解决第N个子问题,就是该问题的解。
该题有些技巧,使用DP的方法解题。
- 所有由1组成的正方形,它的右下角一定是1;
- 假设最大正方形的右下角坐标为(i, j)(下面简称以(i, j)为右下角的最大正方形为(i, j)),那么:
- (i - 1, j) 也一定是一个正方形,并且其边长 = len(i, j) - 1;
- (i, j - 1)也一定是一个正方形,并且其边长 = len(i, j) - 1;
- (i - 1, j - 1)也一定是一个正方形,并且其边长 = len(i, j) - 1;
- 若以上3种正方形的边长都为
a
,len(i, j) = a + 1
;若以上边长分别为a
,b
,c
,则len(i, j) = min(a, b, c) + 1
。因为如果取最大值,则有可能正方形的三个角会缺一个角,则不能构成正方形; - 若当前值为0,则不构成正方形,边长则为0;
DP的规则我们已经找到了,即需要一个记录当前点为右下角的正方形的边长矩阵,然后逐步求解,每次记录最长边长的正方形,遍历完成后计算面积即可。
代码
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.size() == 0) {
return 0;
}
int maxLen = 0;
// 初始化dp, 记录当前右下角为最大正方形的边长。
vector<vector<int>> dp(matrix.size());
for (int i = 0; i < matrix.size(); ++i) {
dp[i].resize(matrix[i].size(), 0);
}
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[i].size(); ++j) {
if (matrix[i][j] == '1') {
if (i <= 0 || j <= 0) {
dp[i][j] = 1;
} else {
dp[i][j] = min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;
}
maxLen = max(maxLen, dp[i][j]);
}
}
}
return maxLen * maxLen;
}
};