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

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