LeetCode 1277. 统计全为 1 的正方形子矩阵(DP)

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 <= arr.length <= 300
1 <= arr[0].length <= 300
0 <= arr[i][j] <= 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-square-submatrices-with-all-ones
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • dp[i][j] 表示 以(i,j)右下角的最大正方形边长
  • 第一行、第一列肯定最大是1(矩阵值为1的话)
  • 其他为 1 位置的最大边长跟它相邻的几块的关系:等于左上方向3个最短的边长+1
  • 正方形的个数等于最大的边长
    在这里插入图片描述
class Solution {
public:
    int countSquares(vector<vector<int>>& matrix) {
    	int m = matrix.size(), n = matrix[0].size(), i, j, count = 0;
    	vector<vector<int>> dp(m,vector<int>(n,0));
    	//dp[i][j] 表示 以i,j为右下角的最大正方形边长
    	for(i = 0; i < m; ++i)
    	{
    		for(j = 0; j < n; ++j)
    		{
    			if(i==0 || j==0)
    				dp[i][j] = matrix[i][j];//最多边长1
    			else if(matrix[i][j]==1)
    				dp[i][j] = 1+min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]));
    			count += dp[i][j];
    		}
    	}
    	return count;
    }
};

另评论区Gremist优化了内存,原地算法

class Solution {
public:
    int countSquares(vector<vector<int>>& matrix) {
        int ans = 0;
        for (int i = 0; i < matrix.size(); i++) {
            for (int j = 0; j < matrix[0].size(); j++) {
                if (i && j && matrix[i][j]) {
                    matrix[i][j] += min({matrix[i-1][j-1], matrix[i-1][j], matrix[i][j-1]});
                }
                ans += matrix[i][j];
            }
        }
        return ans;
    }
};
发布了862 篇原创文章 · 获赞 2460 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/qq_21201267/article/details/105588317