统计全为1的正方形子矩阵--动态规划

leetcode 1277

统计全为1的正方形子矩阵

给你一个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,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)的大小

解法2:动态规划

这一解法是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)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(动态规划,算法,动态规划,leetcode,数据结构)