本文涉及的基础知识点
C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频
LeetCode1074. 元素和为目标值的子矩阵数量
给出矩阵 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 子矩阵。
示例 3:
输入:matrix = [[904]], target = 0
输出:0
提示:
1 <= matrix.length <= 100
1 <= matrix[0].length <= 100
-1000 <= matrix[i][j] <= 1000
-108 <= target <= 108
二维前缀和
计算二维前缀和pre2。三层循环:
c1 = 0 to C-1 c2 = c1 to C-1 r = 0 to R -1
old[0] =1 ,old记录mat[0…r1][c1…c2]之和的数量,r1 ∈ \in ∈ [0,r-1]。ans += old[x - target] x = mat[0…r][c1…c2]之和。即顶部任意,底部为r,左为c1,右为c2和为target的子矩阵数量。
代码
核心代码
template<class T = int>
class CPreSum2 {
public:template<class _Pr>CPreSum2(int rowCnt, int colCount, _Pr pr) :m_iRowCnt(rowCnt), m_iColCnt(colCount) {m_vSum.assign(rowCnt + 1, vector<int>(colCount + 1));for (int r = 0; r < rowCnt; r++) {for (int c = 0; c < colCount; c++) {m_vSum[r + 1][c + 1] = m_vSum[r][c + 1] + m_vSum[r + 1][c] - m_vSum[r][c] + pr(r, c);}}}T Get(int left, int top, int right, int bottom)const {return m_vSum[bottom + 1][right + 1] - m_vSum[top][right + 1] - m_vSum[bottom + 1][left] + m_vSum[top][left];}T GetTopLeft(int bottom, int right) { return m_vSum[bottom+1][right+1]; }T GetBottomRight(int top, int left) { return Get(left, top, m_iColCnt - 1, m_iRowCnt - 1); }vector<vector<T>> m_vSum;const int m_iRowCnt, m_iColCnt;
};class Solution {public:int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {const int R = matrix.size();const int C = matrix[0].size();CPreSum2 ps(R, C, [&](int r, int c) {return matrix[r][c]; });int ans = 0;for (int c1 = 0; c1 < C; c1++) {for (int c2 = c1; c2 < C; c2++) {unordered_map<int, int> cnt;cnt[0] = 1;for (int r = 0; r < R; r++) {const int sum = ps.Get(c1, 0, c2, r);ans += cnt[sum - target];cnt[sum]++;}}}return ans;}};
单元测试
vector<vector<int>> matrix;int target;TEST_METHOD(TestMethod11){matrix = { {0,1,0},{1,1,1},{0,1,0} }, target = 0;auto res = Solution().numSubmatrixSumTarget(matrix, target);AssertEx(4, res);}TEST_METHOD(TestMethod12){matrix = { {1,-1},{-1,1} }, target = 0;auto res = Solution().numSubmatrixSumTarget(matrix, target);AssertEx(5, res);}TEST_METHOD(TestMethod13){matrix = { {904} }, target = 0;auto res = Solution().numSubmatrixSumTarget(matrix, target);AssertEx(0, res);}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。