题目
题目解析
本题要求计算一个矩阵中所有子矩阵的数量,其中子矩阵的元素总和等于给定的目标值 target。
子矩阵通过选择矩阵的某个矩形区域定义,我们需要遍历可能的矩阵区域并统计满足条件的子矩阵。
解题思路
由于直接枚举所有可能的子矩阵会导致时间复杂度过高 (O(n^4)),我们可以通过以下两步进行优化:
-
将二维问题转化为一维问题:
- 固定矩阵的上下边界,计算对应的列和,形成一个一维数组。
- 目标变为找到这个一维数组中所有和为
target的子数组数量。
-
利用前缀和和哈希表优化子数组求和问题:
- 通过前缀和快速判断某个区间的子数组和是否等于
target。 - 使用哈希表记录前缀和的出现次数,从而快速计算符合条件的子数组。
- 通过前缀和快速判断某个区间的子数组和是否等于
实现步骤
-
遍历上下边界:
- 枚举矩阵的顶部边界
top和底部边界bottom。 - 固定
top和bottom后,计算列和数组colSums。
- 枚举矩阵的顶部边界
-
利用前缀和优化子数组求和问题:
- 遍历列和数组,计算当前的前缀和
prefixSum。 - 检查哈希表中是否存在
prefixSum - target,如果存在,则说明当前前缀和中存在一个区间满足条件。 - 更新哈希表中当前前缀和的出现次数。
- 遍历列和数组,计算当前的前缀和
-
累加计数:
- 对于每对上下边界,累加所有满足条件的子矩阵数量。
代码实现
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int solution(vector<vector<int>>& matrix, int target) {
int rows = matrix.size();
int cols = matrix[0].size();
int count = 0;
// 遍历每对可能的上下边界
for (int top = 0; top < rows; ++top) {
vector<int> colSums(cols, 0); // 当前上下边界的列和
for (int bottom = top; bottom < rows; ++bottom) {
// 更新列和
for (int col = 0; col < cols; ++col) {
colSums[col] += matrix[bottom][col];
}
// 利用前缀和和哈希表计算满足条件的子矩阵数量
unordered_map<int, int> prefixSumCount;
prefixSumCount[0] = 1; // 初始前缀和为0
int prefixSum = 0;
for (int col = 0; col < cols; ++col) {
prefixSum += colSums[col];
if (prefixSumCount.find(prefixSum - target) != prefixSumCount.end()) {
count += prefixSumCount[prefixSum - target];
}
prefixSumCount[prefixSum]++;
}
}
}
return count;
}
int main() {
vector<vector<int>> v1 = {{-1, 1, 0}, {1, 1, 1}, {0, 1, 0}};
vector<vector<int>> v2 = {{-1, -1}, {-1, 1}};
vector<vector<int>> v3 = {{-1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
cout << (solution(v1, 0) == 7) << endl;
cout << (solution(v2, 0) == 2) << endl;
cout << (solution(v3, 10) == 2) << endl;
return 0;
}
示例讲解
-
输入矩阵
v1 = [[-1, 1, 0], [1, 1, 1], [0, 1, 0]],目标值target = 0:- 固定
top = 0,bottom = 0时,计算colSums后求和为目标值的子数组数量。 - 固定
top = 0,bottom = 1时,重复上述操作。 - 累计总和,最终返回结果为
7。
- 固定
-
输入矩阵
v2 = [[-1, -1], [-1, 1]],目标值target = 0:- 类似方法统计满足条件的子矩阵,结果为
2。
- 类似方法统计满足条件的子矩阵,结果为
-
输入矩阵
v3 = [[-1, 2, 3], [4, 5, 6], [7, 8, 9]],目标值target = 10:- 累计统计结果为
2。
- 累计统计结果为
复杂度分析
-
时间复杂度:
- 外层两层循环枚举上下边界,时间复杂度为
O(rows^2)。 - 内层利用哈希表计算子数组数量,时间复杂度为
O(cols)。 - 总时间复杂度为
O(rows^2 X cols)。
- 外层两层循环枚举上下边界,时间复杂度为
-
空间复杂度:
- 使用了额外的
colSums数组和prefixSumCount哈希表,空间复杂度为 (O(\text{cols}))。
- 使用了额外的
总结
本题通过转化为一维问题,结合前缀和和哈希表优化,实现了高效计算满足条件的子矩阵数量的目标。