相关文章:C++算法:前缀和与哈希表实战
目录
1.连续数组
https://leetcode.cn/problems/contiguous-array/


理解题意
在二进制数组中找相同数量的0和1的最长子数组,返回其长度
算法原理
本题如果是按照题目要求,依次找到数量相同且连续的0和1,那么是相对较难的,而我们可以转化题目要求:将0转化为-1,由于1不变,所以当连续数组和为0时,就证明这一段的子数组满足题目要求。
与上一篇文章中:和为k的子数组,题目相似。不同点在于本题是在找长度,使用unordered_map<int, int> hash;时,需要存储的是前缀和与下标。并且,需要先定义hash[0] = -1;同样模拟实现前缀和。
细节:
1.存入哈希表的时机:使用完之后,丢进哈希表
2.有重复的<sum, i> ,保留前一对<sum, i>
3.长度:因为是求下标,所以为i- j:

class Solution
{
public:
int findMaxLength(vector<int>& nums)
{
unordered_map<int, int> hash;
hash[0] = -1;
int sum = 0, ret = 0;
for(int i = 0; i < nums.size(); i++)
{
sum += nums[i] == 0 ? -1 : 1;
if(hash.count(sum)) ret = max(ret, i - hash[sum]);
else hash[sum] = i;
}
return ret;
}
};
2.矩阵区域和
https://leetcode.cn/problems/matrix-block-sum/description/


理解题意
以示例一为例:
k=1,表示在指定区域周围多拓展1格,返回值是将其中的数字依次相加求和。
原矩阵为mat,返回矩阵为answer

算法原理
本题是一道二维前缀和题目,我们先自行推导公式:

确定代码条件:

考虑下标映射关系,对mat而言,起始下标为(0,0),对dp和ans而言,起始下标为(1,1):

class Solution {
public:
vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + mat[i - 1][j - 1];
vector<vector<int>> ret(m, vector<int>(n));
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
{
int x1 = max(0, i - k) + 1;
int y1 = max(0, j - k) + 1;
int x2 = min(m - 1, i + k) + 1;
int y2 = min(n - 1, j + k) + 1;
ret[i][j] = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1];
}
return ret;
}
};
本章完。