【力扣:1504】统计全1子矩阵

统计全1子矩阵个数

思路1:首先考虑深度优先模拟,从【0,0】出发向下、右扩展,符合条件res++,最后输出res,比较直观,但重复进行了大量节点遍历操作,时间复杂度较高,数据量大时会超时

cpp 复制代码
class Solution {
    unordered_set<int>set;
    int res=0;
    void get(vector<vector<int>>& mat,int start_r,int start_c,int row,int col){
        if(row>=mat.size()||col>=mat[0].size()||
        set.count(start_r+(start_c+((row+col*151)*151))*151)) return;
        for(int i=start_r;i<=row;i++){
            if(!mat[i][col]) return;
        }
        for(int i=start_c;i<=col;i++){
            if(!mat[row][i]) return;
        }
        res++;
        set.insert(start_r+(start_c+((row+col*151)*151))*151);
        get(mat,start_r,start_c,row+1,col);
        get(mat,start_r,start_c,row,col+1);
    }
public:
    int numSubmat(vector<vector<int>>& mat) {
        for(int i=0;i<mat.size();i++){
            for(int j=0;j<mat[0].size();j++){
                get(mat,i,j,i,j);
            }
        }
        return res;
    }
};

思路2:单考虑行或列时每增加1个1,结果增加 行或列1个数+1,那么多行多列时每增加一行或一列增加(1+2+...+n)*(m+1),加列时:n为行数,m为原来列数,实际上情景就是第一个图的拓展,只不过矩形中的1实际上是长度相等的全1矩形

因而仅需要使用一个二维数组tmp存储targetij及前有几个连续的1,然后从上到下加上min(tmpij,tmp_pre_min)即可

cpp 复制代码
class Solution {
public:
    int numSubmat(vector<vector<int>>& mat) {
        int n = mat.size();
        int m = mat[0].size();
        vector<vector<int> > row(n, vector<int>(m, 0));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (j == 0) {
                    row[i][j] = mat[i][j];
                } else if (mat[i][j]) {
                    row[i][j] = row[i][j - 1] + 1;
                }
                else {
                    row[i][j] = 0;
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                int col = row[i][j];
                for (int k = i; k >= 0 && col; --k) {
                    col = min(col, row[k][j]);
                    ans += col;
                }
            }
        }
        return ans;
    }
};

单调栈优化后代码:

cpp 复制代码
class Solution {
public:
    int numSubmat(vector<vector<int>>& mat) {
        int n = mat.size();
        int m = mat[0].size();
        vector<vector<int> > row(n, vector<int>(m, 0));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (j == 0) {
                    row[i][j] = mat[i][j];
                } else if (mat[i][j]) {
                    row[i][j] = row[i][j - 1] + 1;
                }
                else {
                    row[i][j] = 0;
                }
            }
        }
        int ans = 0;
        for (int j = 0; j < m; ++j) { 
            int i = 0; 
            stack<pair<int, int> > Q; 
            int sum = 0; 
            while (i <= n - 1) { 
                int height = 1; 
                while (!Q.empty() && Q.top().first > row[i][j]) {
                  	// 弹出的时候要减去多于的答案
                    sum -= Q.top().second * (Q.top().first - row[i][j]); 
                    height += Q.top().second; 
                    Q.pop(); 
                } 
                sum += row[i][j]; 
                ans += sum; 
                Q.push({ row[i][j], height }); 
                i++; 
            } 
        } 
        return ans;
    }
};
相关推荐
Sagittarius_A*1 小时前
后量子密码|通识认知 03|量子威胁辟谣:Grover 算法对对称密码的影响与误区
算法·信息安全·密码学·量子计算·pqc·后量子密码
QAQo7T3 小时前
Python组蓝桥杯备赛超详细知识点总结笔记_排序算法篇
笔记·python·算法·蓝桥杯·排序算法
千里之行,始于足下sanhai3 小时前
P8686 [蓝桥杯 2019 省 A] 修改数组 - 数字魔法大冒险 题解
c++·算法·动态规划
小星星闪亮登场3 小时前
Codeforces Round 1115 ( Div. 2)
数据结构·c++·算法·贪心算法·排序算法·codeforces
计算机小白一个3 小时前
蓝桥杯 Java B 组之哈希表应用(两数之和、重复元素判断)
java·数据结构·算法·蓝桥杯
Loge编程生活3 小时前
打卡信奥刷题(3449)用C++实现信奥题 P10429 [蓝桥杯 2024 省 B] 拔河
开发语言·数据结构·c++·算法·青少年编程
2601_957174654 小时前
大模型算法 简单 容易 用这个方法
算法
VALENIAN瓦伦尼安教学设备4 小时前
激光对中仪采购要点
数据库·嵌入式硬件·算法
Forever Nore6 小时前
LeetCode 1 两数之和
算法·leetcode·职场和发展
To_OC6 小时前
LC 3 无重复字符的最长子串:从入门滑动窗口到优化写法,再也不怕面试官追问
javascript·算法·leetcode