前缀和专题:和为 k 的子数组与和可被 k 整除的子数组
前缀和结合哈希表解决子数组求和问题。对于和为 k 的子数组,遍历数组维护当前前缀和,查询哈希表中是否存在 sum-k 的前缀和并累加计数。对于和可被 k 整除的子数组,利用同余定理,若两前缀和对 k 取模结果相同则其差值可被 k 整除。需注意处理负数取模问题,统一使用 (sum % k + k) % k 保证余数为正。该方法将时间复杂度优化至 O(n)。

前缀和结合哈希表解决子数组求和问题。对于和为 k 的子数组,遍历数组维护当前前缀和,查询哈希表中是否存在 sum-k 的前缀和并累加计数。对于和可被 k 整除的子数组,利用同余定理,若两前缀和对 k 取模结果相同则其差值可被 k 整除。需注意处理负数取模问题,统一使用 (sum % k + k) % k 保证余数为正。该方法将时间复杂度优化至 O(n)。

题目链接:
题目描述:

题目示例:

思路:
设 i 为数组中的任意位置,用 sum[i] 表示 [0, i] 区间内所有元素的和
想知道有多少个**「以 i 为结尾的和为 k 的子数组」**,就要找到有多少个起始位置为 x1, x2, x3...使得 [x, i] 区间内的所有元素的和为 k。那么 [0, x] 区间内的和是不是就是 sum[i] - k 了。于是问题就变成:
我们不用真的初始化一个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于 sum[i] - k。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每一种前缀和出现的次数
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int,int> hash;
hash[0]=1;
int n=nums.size();
int sum=0,ret=0;
for(auto x:nums) {
sum+=x;
if(hash.count(sum-k)) ++ret;
hash[sum]++;
}
return ret;
}
};
题目链接:
题目描述:

题目示例:

同余定理:
如果 (a - b) % n == 0,那么我们可以得到一个结论:a % n == b % n。用文字叙述就是,如果两个数相减的差能被 n 整除,那么这两个数对 n 取模的结果相同。
例如:(26 - 2) % 12 == 0,那么 26 % 12 == 2 % 12 == 2。
负数取模问题:
思路:
与上道题思路一样
设 i 为数组中的任意位置,用 sum[i] 表示 [0, i] 区间内所有元素的和
【0,x-1】区间内所有元素之和等于 a ,【0,i】区间内所有元素的和等于 b,可得 (b - a) % k == 0【0,x-1】区间与【0,i】区间内的前缀和同余。于是问题就变成:找到在【0,i-1】区间内,有多少前缀和的余数等于 sum[i] % k 的即可我们不用真的初始化一个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于 sum[i] % k。但是这个我们需要处理一下,确保不会为负数。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每一种前缀和出现的次数
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k) {
unordered_map<int,int> hash;
hash[0%k]=1;//0 这个数的余数
int sum,ret=0;
for(auto x:nums) {
sum+=x;//算出当前位置的前缀和
int r=(sum%k+k)%k;
if(hash.count(r)) ret+=hash[r];
hash[r]++;
}
return ret;
}
};
**总结:**引入同余定理处理负数取模问题,同样采用哈希表优化查询效率,通过维护前缀和哈希表,将时间复杂度优化至 O(n),展示了前缀和技巧在子数组统计问题中的高效应用

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online