题目描述
给出矩阵 matrix 和目标值 target,返回元素总和等于目标值的非空子矩阵的数量。
子矩阵 x1, y1, x2, y2 是满足 x1 <= x <= x2 且 y1 <= y <= y2 的所有单元 matrix[x][y] 的集合。
如果 (x1, y1, x2, y2) 和 (x1', y1', x2', y2') 两个子矩阵中部分坐标不同(如:x1 != x1'),那么这两个子矩阵也不同。
示例1
输入:matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
输出:4
解释:四个只含 0 的 1x1 子矩阵。
示例2
输入:matrix = [[1,-1],[-1,1]], target = 0
输出:5
解释:两个 1x2 子矩阵,加上两个 2x1 子矩阵,再加上一个 2x2 子矩阵。
解题思路
三种方法
1、朴素遍历
2、stl哈希优化(结果时间还增加了。。)
3、手写hash 64ms!
class Solution {
public:
int s[110][110];
int h[211]; // hash,开放寻址法,开输入两到三倍的第一个质数,并用该质数作为mod
int cnt[211];
int find(int x)
{
int t = (x % 211 + 211) % 211;
while(h[t] != 0x3f3f3f3f && h[t] != x)
{
t ++;
if(t == 211)t = 0;
}
return t;
}
int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
int n = matrix.size();
int m = matrix[0].size();
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= m ; j ++)
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + matrix[i-1][j-1];
int res = 0;
// 朴素版 750ms
// for(int i = 1 ; i <= n ; i ++)
// for(int j = 1 ; j <= m ; j ++)
// for(int q = i ; q <= n ; q ++)
// for(int w = j ; w <= m ; w ++)
// if(target == s[q][w] + s[i-1][j-1] - s[i-1][w] - s[q][j-1])
// res ++;
//STL优化 1100ms
// unordered_map <int , int> mp;
// for(int top = 1 ; top <= n ; top ++)
// for(int down = top ; down <= n ; down ++)
// {
// mp.clear();
// mp[0] ++;
// for(int right = 1 ; right <= m ; right ++)
// {
// int t = s[down][right] - s[top-1][right];
// res += mp[t - target];
// mp[t] ++;
// }
// }
// 手写hash 64ms
for(int top = 1 ; top <= n ; top ++)
for(int down = top ; down <= n ; down ++)
{
memset(h , 0x3f , sizeof h);
memset(cnt , 0 , sizeof cnt);
h[find(0)] = 0;
cnt[find(0)] ++;
for(int right = 1 ; right <= m ; right ++)
{
int t = s[down][right] - s[top-1][right];
if(h[find(t-target)] != 0x3f3f3f3f)
res += cnt[find(t - target)];
h[find(t)] = t;
cnt[find(t)] ++;
}
}
return res;
}
};