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

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

题目:给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。

这是一个动态规划问题,有一些值得注意的地方。动态规划的思想就是将当前问题,拆成子问题,并且由子问题的值组合得到当前问题的值。这样我们就可以通过遍历小问题,得到我们想要的大问题的值。通常小问题的值,是很容易求得的。

一般来说,我们经常会保存最优值来组合得到更大问题的值。在这个问题中,最优值对求解更大问题的值却没有帮助,因此我们需要转换思路,观察具体矩阵可以得到一个递推关系。

例如:
输 入 矩 阵 [ 0 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ] 最 优 值 矩 阵 [ 0 , 1 , 1 1 , 3 , 6 1 , 6 , 11 ] 输入矩阵 \begin{bmatrix} 0,1,1\\1,1,1\\1,1,1 \end{bmatrix}\\ 最优值矩阵 \begin{bmatrix} 0,1,1\\1,3,6\\1,6,11 \end{bmatrix}\\ 0,1,11,1,11,1,10,1,11,3,61,6,11
假设输入矩阵是 A A A,我们希望能找到一个 S [ i ] [ j ] S[i][j] S[i][j]与小问题最优值之间的关系
[ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ 0 ] [ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ 1 ] \begin{bmatrix} ***\\***\\**0 \end{bmatrix} \begin{bmatrix} ***\\***\\**1 \end{bmatrix}\\ 01
假设 A [ i ] [ j ] = 0 A[i][j]=0 A[i][j]=0,则容易得知: S [ i ] [ j ] = S [ i ] [ j − 1 ] + S [ i − 1 ] [ j ] − S [ i − 1 ] S [ j − 1 ] S[i][j]=S[i][j-1]+S[i-1][j]-S[i-1]S[j-1] S[i][j]=S[i][j1]+S[i1][j]S[i1]S[j1]

可是当 A [ i ] [ j ] = 1 A[i][j]=1 A[i][j]=1时,如何找到 S [ i ] [ j ] S[i][j] S[i][j]与子问题之间的关系。

相比于包含 A [ i ] [ j ] = 0 A[i][j]=0 A[i][j]=0,这里多了包含 A [ i ] [ j ] A[i][j] A[i][j]的正方形数,可得到 S [ i ] [ j ] = S [ i ] [ j − 1 ] + S [ i − 1 ] [ j ] − S [ i − 1 ] S [ j − 1 ] + C o u n t ( c o n t a i n ( A [ i ] [ j ] ) ) S[i][j]=S[i][j-1]+S[i-1][j]-S[i-1]S[j-1]+Count(contain(A[i][j])) S[i][j]=S[i][j1]+S[i1][j]S[i1]S[j1]+Count(contain(A[i][j]))。如何计算包含 A [ i ] [ j ] A[i][j] A[i][j]的正方形数?如果暴力搜索,那么将会产生 O ( m i n ( i , j ) 2 ) O(min(i,j)^2) O(min(i,j)2)的复杂度。从最优值中能否找到关系。笔者试了挺久。并没有找到合适的关系。

但是我们找到了问题的关键所在,计算包含 A [ i ] [ j ] A[i][j] A[i][j]的正方形数。假设我们已知子问题的包含 A [ m ] [ n ] , m < i , n < j A[m][n],m<i,n<j A[m][n],m<i,n<j的正方形数 B [ m ] [ n ] B[m][n] B[m][n]同时也是最大正方形边长)。那么问题就好解决了。

如图所示:
B [ m , n ] = [ ∗ , ∗ , ∗ ∗ , 1 , 2 ∗ , 2 , ? ] 可 以 由 此 写 出 部 分 矩 阵 [ ∗ , 1 , 1 1 , 1 , 1 1 , 1 , 1 ] 可 知 B [ i , j ] = 2 B[m,n]=\begin{bmatrix} *,*,*\\*,1,2\\*,2,? \end{bmatrix}\\ 可以由此写出部分矩阵 \begin{bmatrix} *,1,1\\1,1,1\\1,1,1 \end{bmatrix}\\ 可知B[i,j]=2 B[m,n]=,,,1,2,2,?,1,11,1,11,1,1B[i,j]=2

如下面两张图所示:包含 A [ i ] [ j ] A[i][j] A[i][j]的正方形数(最大正方形边长)实际上为 min ⁡ ( B [ i − 1 , j ] , B [ i , j − 1 ] , B [ i − 1 , j − 1 ] ) + 1 \min(B[i-1,j],B[i,j-1],B[i-1,j-1])+1 min(B[i1,j],B[i,j1],B[i1,j1])+1

在这里插入图片描述
在这里插入图片描述

则得到递推方程:
B [ i , j ] = { 0 A[i,j]=0 min ⁡ ( B [ i − 1 , j ] , B [ i , j − 1 ] , B [ i − 1 , j − 1 ] ) + 1 A[i,j]=1 则 所 有 正 方 形 数 目 为 : ∑ i ∈ B B [ i , j ] B[i,j]= \begin{cases} 0& \text{A[i,j]=0}\\ \min(B[i-1,j],B[i,j-1],B[i-1,j-1])+1& \text{A[i,j]=1} \end{cases}\\ 则所有正方形数目为:\\ \sum_{i\in B}B[i,j] B[i,j]={0min(B[i1,j],B[i,j1],B[i1,j1])+1A[i,j]=0A[i,j]=1iBB[i,j]
代码实现如下:

int countSquares(vector<vector<int>>& matrix) {
    if(matrix.size()==0) return 0; 
    int m = matrix.size();
    int n = matrix[0].size();
    int sum = 0;
    for(int i = 0;i < m;++i) sum+=matrix[i][0];
    for(int j = 0;j < n;++j) sum+=matrix[0][j];
    sum-=matrix[0][0];
    for(int i = 1;i <m;++i){
        for(int j = 1;j < n;++j){
            if(matrix[i][j]==1){
                matrix[i][j] = min(matrix[i-1][j],matrix[i][j-1]);
                matrix[i][j] = min(matrix[i-1][j-1],matrix[i][j]);
                ++matrix[i][j];
                sum+=matrix[i][j];
            }
        }
    }
    return sum;
}

小结

对于动态规划问题,有时不一定需要找到最优值原问题与子问题的关系。采取另外的方式去寻找递推关系,或许会更好。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值