【前缀和】B007_LC_统计全 1 子矩形(暴力 / 预处理行的前缀和 + 数学组合)

一、Problem

Given a rows * columns matrix mat of ones and zeros, return how many submatrices have all ones.

Input: mat = [[1,0,1],
              [1,1,0],
              [1,1,0]]
Output: 13
Explanation:
There are 6 rectangles of side 1x1.
There are 2 rectangles of side 1x2.
There are 3 rectangles of side 2x1.
There is 1 rectangle of side 2x2. 
There is 1 rectangle of side 3x1.
Total number of rectangles = 6 + 2 + 3 + 1 + 1 = 13.

Constraints:

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

二、Solution

方法一:暴力

思路

固定一个左上角 (a, b),然后枚举右下角 (c, d),检查该两点合成的矩阵是否全 1

剪枝:如果在某一列 y 遇到了一个 0,那么以 (a, b) 为左上角时枚举右下角最多也只能枚举到 (c, y),y 后面那些列都不行了

class Solution {
public:
    int numSubmat(vector<vector<int>>& g) {
    	int n = g.size(), m = g[0].size(), cnt = 0;

    	for (int a = 0; a < n; a++)
		for (int b = 0; b < m; b++) {
			if (g[a][b]) {
				int  mi = m+5;
				for (int c = a; c < n; c++)
				for (int d = b; d < m && d < mi; d++) {
					if (g[c][d] == 1) cnt++;
					else 			{ mi = d; break; }
				}
			}
		}
		return cnt;
    }
};

复杂度分析

  • 时间复杂度:O(n2×m2)O(n^2 × m^2),最坏情况矩阵是全 1 矩阵,可能没有被卡吧
  • 空间复杂度:O(1)O(1)

方法二:预处理行前缀和

思路

先预处理矩阵所有行的前缀和,比如这个网格,预处理后就变成这样了
在这里插入图片描述
比如第一行一共可以数出 1 + 2 + 3 = 6 个矩阵;然后我们以某一个点 (a, b) 为右下角,不断缩短行数来计算出第 a 行上面矩阵的个数。其实这个大矩阵中小矩阵的数也可以推导出来,比如,设 n 为某一个大矩阵内部的 1 × 1 的小矩阵数,则有 cnt=(n+1)×n2cnt = \cfrac{(n+1) × n}{2}比如某一个矩阵由 3 个小矩阵组成,那么一共可以组合出 6 个子矩阵,上式也等价于:1+2+3+...+n=(n+1)×n21+2+3+...+n = \cfrac{(n+1) × n}{2}所以我们累加每一行的前缀和的数值,也可以得到正确结果

class Solution {
public:
    int numSubmat(vector<vector<int>>& g) {
    	int n = g.size(), m = g[0].size(), cnt = 0;
    	vector<vector<int>> s(n+1, vector<int>(m+1));

    	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			s[i][j] = g[i-1][j-1] == 0 ? 0 : s[i][j-1] + 1;
			if (g[i-1][j-1] == 1) {
				int mi = INT_MAX;
				for (int k = i; k >= 0; k--) {
					mi = min(mi, s[k][j]);
					if (mi == 0) //代表该右下角存在0
						break;
					cnt += mi;
				}
			}
		}
		return cnt;
    }
};

复杂度分析

  • 时间复杂度:O(n2×m)O(n^2 × m)
  • 空间复杂度:O(n×m)O(n × m)

可能还有更优的 O(n×m)O(n × m) 的单调栈解法,id = 90258312

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章