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

题目描述

给你一个 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)
posted @ 2020-05-08 23:25  Flix  阅读(395)  评论(0编辑  收藏  举报