• leetcode第196场周赛


    1504. 统计全 1 子矩形

    给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。

    示例 1:

    输入:mat = [[1,0,1],
    [1,1,0],
    [1,1,0]]

    输出:13

    解释:
    有 6 个 1x1 的矩形。
    有 2 个 1x2 的矩形。
    有 3 个 2x1 的矩形。
    有 1 个 2x2 的矩形。
    有 1 个 3x1 的矩形。

    矩形数目总共 = 6 + 2 + 3 + 1 + 1 = 13 。

    示例 2:

    输入:mat = [[0,1,1,0],
    [0,1,1,1],
    [1,1,1,0]]

    输出:24

    解释:
    有 8 个 1x1 的子矩形。
    有 5 个 1x2 的子矩形。
    有 2 个 1x3 的子矩形。
    有 4 个 2x1 的子矩形。
    有 2 个 2x2 的子矩形。
    有 2 个 3x1 的子矩形。
    有 1 个 3x2 的子矩形。

    矩形数目总共 = 8 + 5 + 2 + 4 + 2 + 2 + 1 = 24 。

    示例 3:

    输入:mat = [[1,1,1,1,1,1]]

    输出:21

    示例 4:

    输入:mat = [[1,0,1],[0,1,0],[1,0,1]]

    输出:5

    提示:

    1 <= rows <= 150
    1 <= columns <= 150
    0 <= mat[i][j] <= 1

    算法1 暴力枚举 + check O(n^6)

    思路

    先枚举矩阵上下两边,再枚举矩阵左右两边,check,不满足条件就break,满足条件sum++。(稍微优化一下就是二维前缀和判断全1)

    本蒟蒻还是太菜,比赛的时候只会用最暴力的方法,连二维前缀和都没有想到,n^6铁定超时。。。

    class Solution {
    public:
        int numSubmat(vector<vector<int>>& mat) {
            int n = mat.size(), m = mat[0].size();
            int sum = 0;
            for(int i = 0; i < n; i ++){
                for(int j = i; j < n; j ++){
                    for(int l = 0; l < m; l ++){
                        for(int r = l; r < m; r ++){
                            bool flag = true;
                            for(int p = i; p <= j; p ++){
                                for(int q = l; q <= r; q ++){
                                    if(mat[p][q] == 0){
                                        flag = false;
                                        break;
                                    }
                                    if(!flag) break;
                                }
                            }
                            if(flag) sum ++;
                        }
                    }
                }
            }
        return sum;
        }
    };
    

    算法2 枚举上下边界,二维压成一维 O(n^3)

    思路

    参考的b站上大佬的思路,枚举上下边界,二维压成一维 是常用的套路,类似的题可以做做面试题 17.24. 最大子矩阵

    枚举上下边界i和j,二维压成一维,sum[k]记录当前列k的总和,sum[k]=i-j+1说明列k全1,连续cnt次列全1给ans贡献1+2+...+cnt。为什么呢,举个列子:矩阵[[1,1,1]]有三次列连续列全1,所以有1+2+3个全一子矩阵。

    class Solution {
    public:
        int numSubmat(vector<vector<int>>& mat) {
            int n = mat.size(), m = mat[0].size();
            vector<int> sum(m, 0);
            int ans = 0;
            for(int i = 0; i < n; i ++){
                for(int k = 0; k < m; k ++) sum[k] = 0;
                for(int j = i; j < n; j ++){
                   for(int k = 0; k < m; k ++) sum[k] += mat[j][k];
                    int cur = j - i + 1, cnt = 0;
                    for(int k = 0; k < m; k ++){
                       
                        if(sum[k] == cur){
                            cnt ++;
                            ans += cnt;
                        }
                        else cnt = 0;
                    }
                }
            }
            return ans;
        }   
    };
    

    算法3 dp O(n^3)

    思路

    矩阵里每个点(i.j)统计他这行左边到他这个位置最多有几个连续的1,存为left[i]j。然后对于每个点(i.j),我们固定子矩形的右下角为(i.j),利用left从该行i向上寻找子矩阵左上角为第k行的矩阵个数。每次将子矩阵个数加到答案中即可。

    class Solution {
    public:
        int numSubmat(vector<vector<int>>& mat) {
            int n = mat.size();
            int m = mat[0].size();
            vector<vector<int> > left(n,vector<int>(m));
            int now = 0;
            for(int i=0;i<n;i++){
                now = 0;
                for(int j=0;j<m;j++){
                    if(mat[i][j] == 1) now ++;
                    else now = 0;
                    left[i][j] = now;
                }
            }
            int ans = 0,minx;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    minx = 0x3f3f3f3f;
                    for(int k=i;k>=0;k--){
                        minx = min(left[k][j],minx);//向上找到最短连续的1个数,要组成全1矩阵,类似于木桶原理,取决于最短边
                        ans += minx;
                    }
                }
            }
            return ans;
        }
    };
    

    参考

    作者:lin-miao-miao
    链接:https://leetcode-cn.com/problems/count-submatrices-with-all-ones/solution/5454-tong-ji-quan-1-zi-ju-xing-by-lin-miao-miao/
    来源:力扣(LeetCode)

  • 相关阅读:
    python gzip get url
    nginx 日志解析,nginx缓存
    Keepalived
    SEO 搜索引擎优化
    检测网站是否支持gzip的本地代码
    使用logrotate做nginx日志轮询
    YUI Compressor下载
    Adobe Illustrator有 机会装一下
    同步时间
    买不起书啊nginx http server filetype:pdf 30刀
  • 原文地址:https://www.cnblogs.com/jst2567421142/p/13266246.html
Copyright © 2020-2023  润新知