[Leetcode 1074] Number of Submatrices That Sum to Target

原题说明

Given a matrix, and a target, return the number of non-empty submatrices that sum to target.

A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2.

Two submatrices (x1, y1, x2, y2) and (x1’, y1’, x2’, y2’) are different if they have some coordinate that is different: for example, if x1 != x1’.

 

Example 1:

Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
Output: 4
Explanation: The four 1x1 submatrices that only contain 0.

Example 2:

Input: matrix = [[1,-1],[-1,1]], target = 0
Output: 5
Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix.

 

Note:

  1. 1 <= matrix.length <= 300
  2. 1 <= matrix[0].length <= 300
  3. -1000 <= matrix[i] <= 1000
  4. -10^8 <= target <= 10^8

解题思路

这题是presum思想的变种二维版本。
首先我们可以把每一行的presum都先计算出来,用一个二维的vector保存。
之后,对任意两个列col1, col2, 计算col1col2之间的所有数的和, 因为对于每一行,我们已经计算了它们对应的presum, 所以,对于col1,col2之间的数,可以通过presum[row][col2+1] - presum[row][col1] 迅速得到。(注意我们开presum数组时,选择多开一个,这样处理了第一个数的和的问题。详细参考c++代码)
我们可以依次得到在列区间col1, col2中,第0行到第row行的所有的数的和。用一个哈希表存下来,边可以查询满足题目要求的Submatrix。相当与又一个presum的思想。可参考leetcode 560题

综上所述,这题通过二维的presum运用的可以得到解答。相关的题目还有leetcode 304 Range Sum Query 2D - Immutable。 大家可以练习下

示例代码 (cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
int numSubmatrixSumTarget(vector<vector<int>>& A, int target) {
int res = 0, m = A.size(), n = A[0].size();
vector<vector<int>> presum(m, vector<int>(n + 1, 0));

for (int i = 0; i < m; i++) {
for (int j = 1; j < n + 1; j++) {
presum[i][j] += presum[i][j - 1] + A[i][j - 1];
}
}

unordered_map<int, int> counter;
for (int col1 = 0; col1 < n + 1; col1++) {
for (int col2 = col1 + 1; col2 < n + 1; col2++) {
counter = {{0,1}};
int cur = 0;
for (int row = 0; row < m; row++) {
cur += presum[row][col2] - presum[row][col1];
res += counter.find(cur - target) != counter.end() ? counter[cur - target] : 0;
counter[cur]++;
}
}
}
return res;
}
};

示例代码 (java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public int numSubmatrixSumTarget(int[][] A, int target) {
int res = 0, m = A.length, n = A[0].length;
for (int i = 0; i < m; i++)
for (int j = 1; j < n; j++)
A[i][j] += A[i][j - 1];
Map<Integer, Integer> counter = new HashMap<>();
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
counter.clear();
counter.put(0, 1);
int cur = 0;
for (int k = 0; k < m; k++) {
cur += A[k][j] - (i > 0 ? A[k][i - 1] : 0);
res += counter.getOrDefault(cur - target, 0);
counter.put(cur, counter.getOrDefault(cur, 0) + 1);
}
}
}
return res;
}
}

示例代码 (python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution(object):
def numSubmatrixSumTarget(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: int
"""
m, n = len(matrix), len(matrix[0])
for row in matrix:
for i in xrange(n - 1):
row[i + 1] += row[i]
res = 0
for i in xrange(n):
for j in xrange(i, n):
c = collections.defaultdict(int)
cur, c[0] = 0, 1
for k in xrange(m):
cur += matrix[k][j] - (matrix[k][i - 1] if i > 0 else 0)
res += c[cur - target]
c[cur] += 1
return res

复杂度分析

m为行数,n为列数。
时间复杂度: O(mn^2)
空间复杂度: O(mn)

视频讲解

我们在Youtube上更新了视频讲解,欢迎关注!

------ 关注公众号:猩猩的乐园 ------