1.题目基本信息
1.1.题目描述
给你一个 m x n 的二进制矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
1.2.题目地址
https://leetcode.cn/problems/count-submatrices-with-all-ones/description/
2.解题方法
2.1.解题思路
单调栈
时间复杂度:O(n)
2.2.解题步骤
第一步,构建rows矩阵,rows[i][j]表示从mat[i][j]开始向左连续为1的个数(包括本身)
第二步,遍历每一列,列号记为j,再遍历每列中的每行,行号即为i
2.1.构建每一列的维护变量。total维护以(i,j)为右下角的全为1的子矩阵个数(如果该列的rows[i][j]非严格递增,则就等于前缀和);stack维护随着rows[i][j]严格递增的单调栈,存储单元形式为(rows[i][j],height*=rows矩阵中(i,j)上面连续不小于rows[i][j]的个数+1)
2.2.遍历每一列,更新total和stack,并将total更新到结果变量result中。total更新:如果rows[i][j]大于或等于单调栈栈顶的元素,则直接将rows[i][j]增加到total中,并入栈即可;如果小于,则将大的元素从栈中弹出,并从total中切除多余的子矩阵数(相当于切成一个非严格递增的rows[i][j]序列)
3.解题代码
Python代码
class Solution:def numSubmat(self, mat: List[List[int]]) -> int:# 思路:单调栈m, n = len(mat), len(mat[0])# 第一步,构建rows矩阵,rows[i][j]表示从mat[i][j]开始向左连续为1的个数(包括本身)rows = [[0] * n for _ in range(m)]for i in range(m):for j in range(n):if mat[i][j] == 1:if j > 0:rows[i][j] = rows[i][j - 1] + 1else:rows[i][j] = 1# 第二步,遍历每一列,列号记为j,再遍历每列中的每行,行号即为iresult = 0for j in range(n):# 2.1.构建每一列的维护变量。total维护以(i,j)为右下角的全为1的子矩阵个数(如果该列的rows[i][j]非严格递增,则就等于前缀和);stack维护随着rows[i][j]严格递增的单调栈,存储单元形式为(rows[i][j],height*=rows矩阵中(i,j)上面连续不小于rows[i][j]的个数+1)total = 0stack = []# 2.2.遍历每一列,更新total和stack,并将total更新到结果变量result中。total更新:如果rows[i][j]大于或等于单调栈栈顶的元素,则直接将rows[i][j]增加到total中,并入栈即可;如果小于,则将大的元素从栈中弹出,并从total中切除多余的子矩阵数(相当于切成一个非严格递增的rows[i][j]序列)for i in range(m):height = 1while stack and stack[-1][0] >= rows[i][j]:preRow, preHeight = stack.pop()height += preHeighttotal -= (preRow - rows[i][j]) * preHeighttotal += rows[i][j]stack.append([rows[i][j], height])result += totalreturn result