# 【前綴和】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

### 方法一：暴力

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(n^2 × m^2)$，最壞情況矩陣是全 1 矩陣，可能沒有被卡吧
• 空間複雜度：$O(1)$

### 方法二：預處理行前綴和

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(n^2 × m)$
• 空間複雜度：$O(n × m)$