补一个坑
目录
以力扣560为例:
力扣1248,优美子数组
力扣974 和可被 K 整除的子数组
力扣523.连续的子数组和
浅谈一下前缀和:
我们通过前缀和数组保存前 n 位的和,presum[1]保存的就是 nums 数组中前 1 位的和,也就是 presum[1] = nums[0], presum[2] = nums[0] + nums[1] = presum[1] + nums[1]. 依次类推,所以我们通过前缀和数组可以轻松得到每个区间的和
for(int i=0;i
下面说说map+前缀和
思路像极了两数之和的问题,找k存在否,我们找target-k就可以
我们可以直接暴力ac,以前缀和加map就是,map存的是各个和以及他对应出现的次数
精华如下图:我们只要统计各个阶段前缀和出现的次数,只要有能和k组成新的前缀和的,那就说明k也是存在的,且presum-k的次数不就是k出现的次数吗,,还是两数之和的问题
至于给map初始0赋值,也是为了能让一开始找到前缀和等于k的位置能计算上,,这个初始化也是必须有的
map给在初始化的时候给0一个元素,,相当于那个前缀和数组的0号下标位置给个初始值
int subarraySum(vector& nums, int k) {
int ans=0;
unordered_mapmp{{0,1}};
int sum=0;
for(int i=0;i
上面这个代码模式可以说是所有map+前缀和的模板代码了
下面给出剩下常见的map+前缀和的问题:
求子数组里面有k个奇数的,,转换一下思路。我们可以把奇数转换为1,偶数是0.。那么整个数组就是0 1组合,,那么找奇数,不就是找子数组和等于k,因为只有奇数才是有值的,偶数0不起作用啊,,转换成这样了
套用上面模板,如下ac:
int numberOfSubarrays(vector& nums, int k) {
unordered_mapmp{{0,1}};
int ans=0;
int sum=0;
for(int i=0;i
同样的模板,只不过数组里面有可能会有负数,所以在除的时候 做一个下标转换
我们只需要知道之前的前缀区间里含有相同余数 (key)的个数。则能够知道当前能够整除 K 的区间个数
啥意思k等于3,,假如当前我8对3余2,,我只要能找到比8小且+k等于8,且%3也等于2的说明, k就是能被整除的,比如5,,前面要是有个5,那么结果就能++一次
ac:
int subarraysDivByK(vector& nums, int k) {
unordered_mapmp{{0,1}};
int sum=0;
int ans=0;
for(int i=0;i
核心一句话:a−b的差值要是k的倍数,那么a除以k的余数必定等于b除以k的余数
也是上一题的核心
这题多了些判断条件
bool checkSubarraySum(vector& nums, int k) {
unordered_mapmp{{0,-1}};
// 防止第一个数和第二个数的和直接是k
//0 -1
int sum=0;
for(int i=0;i=2){
return true;
}
}
else{
mp[key]=i;
}
}
return false;
}
over...