力扣--统计全1子矩阵
力扣–统计全1子矩阵
文章目录
- 力扣--统计全1子矩阵
- 一、题目描述
- 二、分析
- 方法一:枚举
- 三、代码
- 枚举方法的代码
一、题目描述
二、分析
方法一:枚举
- 首先很直观的想法,我们可以枚举矩阵中的每个位置 (i,j),统计以其作为右下角时,有多少个元素全部都是 1的子矩形,那么我们就能不重不漏地统计出满足条件的子矩形个数。
- 那么枚举以后,我们怎么统计满足条件的子矩形个数呢?
- 既然是
枚举以 (i,j) 作为右下角的子矩形个数
,那么我们可以直接暴力地枚举左上角 (k,y),看其组成的矩形是否满足条件,时间复杂度为 O(nm)。但这样无疑会使得时间复杂度变得很高,我们需要另寻他路。 - 我们
预处理row 数组,其中row[i][j] 代表矩阵中 (i,j) 向左延伸连续 1 的个数
,容易得出递推式:
有了row 数组以后,
如果要统计以 (i,j) 为右下角满足条件的子矩形,我们就可以枚举子矩形的高,即第 k行,看当前高度有多少满足条件的子矩形
。由于
我们知道第 k 行到第 i 行「每一行第 j 列向左延伸连续 1 的个数」
row[k][j],row[k+1][j],⋯,row[i][j],因此我们可以知道第 k 行满足条件的子矩形个数就是这些值的最小值
,它代表了「第 k 行到第 ii 行子矩形的宽的最大值」
,公式化来说,即:
因此我们
倒序枚举 k,用num 变量来记录到当前行 i 的最小值,即能在O(n) 的时间内统计出以 (i,j)为右下角满足条件的子矩形个数
。
举个例子吧,如下图的矩阵,我们现在计算以点mat[3][2]为右下角所构成的矩阵中子矩阵全为1的子矩阵的个数。
[0,0,1]
[0,1,1]
[1,1,1]
[1,1,1]
- 首先是第四行,dp[3][2] = 3,所以最小长度为3,所以sum += 3,这里计算的矩阵是只有第四行元素构成的矩阵,如下所示:
[1,1,1], [1,1], [1]
- 向上遍历,第三行时,dp[2][2] = 3,最小长度依然为3,sum += 3,这里计算的矩阵是第三、四行元素构成的矩阵,如下所示:
[1] [1,1] [1,1,1]
[1], [1,1], [1,1,1]
- 继续向上遍历,第二行时,dp[1][2] = 2,此时的最小长度变为2,sum += 2,这里计算的矩阵是第二、三、四行元素构成的矩阵,如下所示:
[1] [1][1]
[1] [1][1]
[1], [1][1]
- 继续向上遍历,第一行时,dp[0][2] = 1,此时的最小长度变为1,sum += 1,这里计算的矩阵是第一、二、三、四行元素构成的矩阵,如下所示:
[1]
[1]
[1]
[1]
- 该点遍历结束,继续循环遍历所有节点后返回sum即可
三、代码
枚举方法的代码
class Solution {public:int numSubmat(vector<vector<int>>& mat) {if(mat.empty()){return 0;}int m = (int)mat.size();int n = (int)mat[0].size();//dp[i][j]代表以i,j坐标为右端点,向左延续连续1的个数。意思是在第i行,j为终点,从j//向左连续1的个数,注意是连续连续连续vector<vector<int>> dp(m,vector<int>(n));for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){//处理边界if(j == 0){dp[i][j] = mat[i][j];}//如果当前位置为1,就代表可以在左边的基础上进行+1else if(mat[i][j] == 1){dp[i][j] = dp[i][j - 1] + 1;}//如果当前位置为0,那么dp代表的是连续1的个数,中间断了,直接赋值为0else {dp[i][j] = 0;}}}//保存最后的结果int sum = 0;//遍历,每次求以i,j坐标为右下角for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){//保存点i,j坐标处向左延续连续1的个数int num = dp[i][j];//向上枚举每一行for(int k = i;k >= 0;k--){//一旦某一行为0,那么求min后都为0,代表没有构成矩阵if(num == 0){break;}//更新结果num = min(num,dp[k][j]);sum += num;}}}return sum;}
};
力扣--统计全1子矩阵相关推荐
- 力扣 统计各位数字都不同的数字个数 C++ 题解
力扣 统计各位数字都不同的数字个数 C++ 题解 文章目录 力扣 统计各位数字都不同的数字个数 C++ 题解 一.完整题目 二.具体思路 三.编写代码 四.测评结果 五.总结评价 一.完整题目 给你一 ...
- LC5454.统计全1子矩阵(矩阵统计)
问题 解题 技巧:矩阵枚举上下边界,用一个sum维护上下边界内每一列的列和,压成一维数组 如果上下边界的差值diff等于这一列的列和sum,则这一列可以用来做矩阵 由于会存在连续并排的列,因此还需要一 ...
- 力扣比赛 5454. 统计全 1 子矩形
给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 . 示例 1: 输入:mat = [[1,0,1], [1,1,0], [1 ...
- LeetCode 1277. 统计全为 1 的正方形子矩阵(DP)
1. 题目 给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数. 示例 1: 输入:matrix = [[0,1,1,1],[1, ...
- 力扣解法汇总2315. 统计星号
目录链接: 力扣编程题-解法汇总_分享+记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描 ...
- C语言求最大正方形子矩阵,动态规划—统计全为1的正方形子矩阵个数|最大正方形...
最大正方形 (统计全为 1 的正方形子矩阵) 解析可以参考leetcode解析 public class Solution { public int countSquares(int[][] matr ...
- 力扣 1832. 判断句子是否为全字母句
题目 全字母句 指包含英语字母表中每个字母至少一次的句子. 给你一个仅由小写英文字母组成的字符串 sentence ,请你判断 sentence 是否为 全字母句 . 如果是,返回 true :否则, ...
- C++算法学习(力扣:1254. 统计封闭岛屿的数目)
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 ). 我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」 ...
- LeetCode 力扣 算法题解 1109. 航班预订统计(Corporate Flight Bookings) n 个航班,它们分别从 1 到 n 进行编号,请返回每个航班预定的座位总数。
文章目录 一.题目描述 示例 1: 示例 2: 提示: 二.Python解题 1.Python代码展示 2.程序逻辑解释 3.复杂度分析 官方解释 三.测试反思 1.历史提交记录 2.提交失败记录 3 ...
最新文章
- Blender多米诺骨牌动画学习教程 The Impossible Domino Run in Blender
- iOS架构-分离静态库.a文件并导出.m伪代码文件(11)
- 有关绑定没有数据显示的问题
- java CAS和AQS
- MongoDB学习笔记Day3
- Linux之CentOS找不到configure
- 镭威视监控怎么复位_三大原因导致海康威视、大华股份近期连续暴跌
- 18寒假最后一测+dijistra模板
- RAPID 信号的互锁和同步 WaitTestAndSet 和 TestAndSet
- 云服务器(Centos)部署SVN
- [jQuery] Zepto的点透问题如何解决?
- On the coexistence of transport protocols in data centers
- React.Component与React.PureComponent的区别
- C#函数学习及常用的类
- 区块链学堂——公有链、私有链、联盟链、侧链、互联链
- Linux-文件结构、快捷键、安装软件和常用命令(1)
- 软件架构之“道”和“术”哲学思考
- win8metro应用磁贴背景修改说明
- 彩票股票金融与运气之研究(二)-飘渺的希望
- 电机编码器调零步骤_什么是调零对位?伺服电机编码器调零对位方法