题目描述
给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。
示例:
输入:matrix =
[
[0,1,1,1],
[1,1,1,1],
[0,1,1,1]
]
输出:15
解释:
边长为 1 的正方形有 10 个。
边长为 2 的正方形有 4 个。
边长为 3 的正方形有 1 个。
正方形的总数 = 10 + 4 + 1 = 15.
输入:matrix =
[
[1,0,1],
[1,1,0],
[1,1,0]
]
输出:7
解释:
边长为 1 的正方形有 6 个。
边长为 2 的正方形有 1 个。
正方形的总数 = 6 + 1 = 7.
题目链接: https://leetcode-cn.com/problems/count-square-submatrices-with-all-ones/
做这题之前,可以先做一下最大正方形。
思路
和最大正方形基本一样。使用动态规划来做,思路如下:
- 状态定义:dp[i][j] 表示以位置 (i,j) 为右下角的全为 1 的正方形边长;
- 状态转移方程:dp[i][j] = min(dp[i-1][j], dp[i-1][j-1], dp[i][j-1]) + 1,也就是当前位置符合条件的边长等于当前位置左边一个位置、左上角一个位置、上面一个位置符合条件边长的最小值加 1;
- 边界条件:当只有一行或者一列时,如果 matrix[i][j] = 1, dp[i][j]=1;否则 dp[i][j]=0.
最后遍历 dp 矩阵,如果 dp[i][j] 不为 0,就把 dp[i][j] 加入到结果当中。
代码如下:
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
if(matrix.empty() || matrix[0].empty()) return 0;
int rows = matrix.size();
int cols = matrix[0].size();
vector<vector<int>> dp(rows, vector<int>(cols, 0));
int ans = 0;
for(int i=0; i<rows; i++){
for(int j=0; j<cols; 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-1][j-1]), dp[i][j-1]) + 1; // 别忘了加 1
}
}
if(dp[i][j]!=0) ans += dp[i][j];
}
}
return ans;
}
};
- 时间复杂度:O(m*n)
m,n 分别为矩阵的行列数。 - 空间复杂度:O(m*n)