给你一个m*n
的矩阵,矩阵中的元素不是0
就是1
,请你统计并返回其中完全由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.
示例2:
输入:matrix =
[
[1,0,1],
[1,1,0],
[1,1,0]
]
输出:7
解释:
边长为 1 的正方形有 6 个。
边长为 2 的正方形有 1 个。
正方形的总数 = 6 + 1 = 7.
思路:其实一个大的正方形矩阵可以有小的正方形组成,我们对每一个正方形往左下方扩展,就能得到正方形的个数,举个例子
1,1,1,1
1,1,1,0
1,0,1,0
我们看第一个元素,往外扩展一圈,得到元素是1,1,1
,再扩展一圈,得到的是1,1,1,0,1
,发现有一个不是正方形,我们就退出扩展,返回扩展的长度1
,依次类推,就能得到正方形子矩阵的个数
完整代码
int expand(int i, int j, int dp[MAXN][MAXN], int rowsize, int colsize)
{
if(dp[i][j]==0)
return 0;
int size=1; //扩展长度
int row, col;
while(size)
{
if(i+size>=rowsize || j+size>=colsize) //超过范围
return size-1;
for(row=i+size,col=j; col<=j+size; col++) //遍历外围行
if(dp[row][col]==0)
return size-1;
for(col=j+size,row=i; row<=i+size; row++)//遍历外围列
if(dp[row][col]==0)
return size-1;
size++;
}
}
int countSquares(int matrix[MAXN][MAXN], int rowsize, int colsize){
int dp[MAXN][MAXN];
int i, j;
int num=0;
for(i=0; i
时间复杂度为O(MNMAX(M,N)),在遍历二维数组的时候时间复杂度为O(M*N),在扩展时还需要遍历一行一列数据
空间复杂度为O(M*N),二维数组(dp)的大小
这一解法是leetcode官方解法,前面的解法是我自己的解法
思路:该解法和上面解法思路基本相同,但是在扩展的时候,使用了动态规划的思想,因此我们需要先了解一下它的动态规划转移方程是怎样的,还有它是如何推导得到的
先看一个例子
1,1,1,1,
1,1,1,1,
1,1,1,1,
1,1,1,1,
我们用f(i,j)作为一个正方形的右下角,它保存着正方形子矩阵的个数
我们可以看到,f(i,j-1),f(i-1,j),f(i-1,j-1)
都表示3个正方形矩阵个数,也就是f(i,j)-1
,即f(i,j-1),f(i-1,j),f(i-1,j-1)
至少等于f(i,j)-1
,因此我们可以得到转移方程
完整代码
int min(int a, int b, int c)
{
if(a
时间复杂度O(M*N)只需遍历一遍二维数组
空间复杂度O(M*N),保存值dp数组
该算法比我的要好得多,不仅简洁,而且时间复杂度降低,其实算法思路是一样的,但是动态规划的思想就是减少重复运算,保存已经计算过的值,以便后来可以重复使用,使用动态规划时应该找出边界条件还有状态转移方程
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/count-square-submatrices-with-all-ones/solution/tong-ji-quan-wei-1-de-zheng-fang-xing-zi-ju-zhen-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。