LeetCode 1277统计全为1的正方形矩阵
-
题目简述:给你一个
m * n
的矩阵,矩阵中的元素不是0
就是1
,请你统计并返回其中完全由1
组成的 正方形 子矩阵的个数。1 <= arr.length <= 300
1 <= arr[0].length <= 300
0 <= arr[i][j] <= 1
-
示例:输入:
[ 0 1 1 1 1 1 1 1 0 1 1 1 ] \left[\begin{matrix}0 & 1 & 1 & 1 \\1 & 1 & 1 & 1 \\0 & 1 & 1 & 1\end{matrix} \right] ⎣⎡010111111111⎦⎤
输出:15解释:边长为 1 的正方形有 10 个 + 边长为 2 的正方形有 4 个 + 边长为 3 的正方形有 1 个 = 15个 。
-
思路:动态规划
-
状态表示:
f[i,j]
表示以点(i,j)
为右下角的正方形的个数 -
状态属性:求正方形个数的总数
-
状态转移:
f[i][j] = min(f[i - 1][j - 1],min(f[i - 1][j],f[i][j - 1])) + 1;
对输入矩阵从左上角往右下角遍历,以大小为
2和3
的正方形举例- 如果边长为
2
的正方形存在,则以右下角(i,j)
点为参照,它的左上角、上方、左方均存在边长为1
的正方形 - 如果边长为
3
的正方形存在,则以右下角(i,j)
点为参照,它的左上角、上方、左方均存在边长为2
的正方形
- 如果边长为
-
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
int ans = 0;
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n, vector<int>(m, 0));
for(int i = 0; i < n; i++) ans += f[i][0] = matrix[i][0];//处理第0列
for(int j = 0; j < m; j++) ans += f[0][j] = matrix[0][j];//处理第0行
if(matrix[0][0] == 1) ans--;//处理(0,0)位置元素,上述过程重复处理
for(int i = 1; i < n; i++)
for(int j = 1; j < m; j++)
{
if(matrix[i][j] == 1)
{
f[i][j] = min(f[i - 1][j - 1], min(f[i - 1][j], f[i][j - 1])) + 1;
ans += f[i][j];
}
}
return ans;
}
};
//优化写法:将动态数组中的第0列和第0行提前初始化为0,多初始化一行一列
//从(1,1)开始遍历,则原来起始处(0,0)变为了(i-1, j-1)
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
int ans = 0;
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if(matrix[i - 1][j - 1] == 1)
{
f[i][j] = min(f[i - 1][j - 1], min(f[i - 1][j], f[i][j - 1])) + 1;
ans += f[i][j];
}
}
return ans;
}
};