1074. Number of Submatrices That Sum to Target

问题:

给定一个二维数组,求子数组之和为target的子数组个数。

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 <= matrix.length <= 300
1 <= matrix[0].length <= 300
-1000 <= matrix[i] <= 1000
-10^8 <= target <= 10^8

  

解法:

560. Subarray Sum Equals K

解法说明

是上述题目的延展,思想一致。

一个数列:Target = Sum(i~j)  =Sum(0~j)-Sum(0~i)    =Sum(j)-Sum(i)

所以:Sum(i) = Sum(j)-Target

那么 直到 第j个元素:和为target的子数组个数cout(sum=target) = cout(sum=当前sum(j)-Target) 到j为止,前缀和(0~x)为(sum(j)-Target)的子数组个数。

 

再考虑:二维数组->降维

固定列(or行,这里我们选择列),

从内部看:对于每一组列(j,k)<第j列到第k列为一组>,幻化成单列,内部进行上面的算法操作。

★幻化成单列:单列里的每个元素=matrix[..][j]+...+matrix[..][k]=Sum(matrix[..][k])-Sum(matrix[..][j-1])

从外部看:要求的子数组,即是将每一组列看作一个整体,各自得出的子数组数,累加即可

每一组列:左右(j,k)两个bound来界定,00,01,02,03,...,0m, 11,12,13,...,1m,...,(m-1)m, mm

 

为了求★的Sum(matrix[..][k]),进行第一轮for循环,

1         for(i=0; i<n; i++){
2             for(j=1; j<m; j++){
3                 matrix[i][j]+=matrix[i][j-1];
4             }
5         }

然后,固定列,排列组合各种组列:

(每一组列:左右(j,k)两个bound来界定,00,01,02,03,...,0m, 11,12,13,...,1m,...,(m-1)m, mm)

1         for(j=0; j<m; j++){
2             for(k=j; k<m; k++){
3                 sumhash={{0,1}};
4                 int presum=0;
5                 ......
6                 }
7             }
8         }

对每一组列,遍历每个元素(row压缩为一个:matrix[..][k]-matrix[..][j-1])

累加,计算前缀和presum。并保存前缀和计数map:sumhash中。

1                 for(i=0; i<n; i++){
2                     presum+=(matrix[i][k]-(j>0?matrix[i][j-1]:0));
3                     ......
4                     sumhash[presum]++;
5                 }

 

对于到目前的 i,为止,sum=target的子数列数目= 前缀和为 当前总和-target 的前缀数组个数。

1                     res+=sumhash.find(presum - target) != sumhash.end() ? sumhash[presum - target] : 0;

 

 

代码参考:

⚠️注意:不用●的写法,而使用count判断存在与否,在进行赋值,减少运算时间。

 1 class Solution {
 2 public:
 3     int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
 4         int i=0, j=0, k=0;
 5         int n=matrix.size(), m=matrix[0].size();
 6         int res=0;
 7             //  |0| 1 |  2  |   3   |
 8             //->|0|0+1|0+1+2|0+1+2+3|★
 9         for(i=0; i<n; i++){
10             for(j=1; j<m; j++){
11                 matrix[i][j]+=matrix[i][j-1];
12             }
13         }
14         unordered_map<int,int>sumhash;
15         for(j=0; j<m; j++){
16             for(k=j; k<m; k++){
17                 sumhash={{0,1}};
18                 int presum=0;
19                 // col-j ~ col-k fixed.  move row
20                 // cause ★, so only to see → value.(matrix[..][k])
21                 // remove 0~j-1 cols, so -matrix[..][j-1]
22                 for(i=0; i<n; i++){
23                     presum+=(matrix[i][k]-(j>0?matrix[i][j-1]:0));
24                     res+=sumhash.find(presum - target) != sumhash.end() ? sumhash[presum - target] : 0;
25                         //●sumhash[presum-target];//k:sum(x), v:cout(sum(x))
26                     //target=sum(i~j)=sum(j)-sum(i)
27                     //sum(i)=sum(j)-target
28                     //until j: cout(sum=target)=cout(sum=sum(i))
29                     sumhash[presum]++;
30                 }
31             }
32         }
33         return res;
34     }
35 };

 

posted @ 2020-05-17 14:06  habibah_chang  阅读(149)  评论(0编辑  收藏  举报