classSolution{publicintsubarraySum(int[] nums,int k){int[] preSum =newint[nums.length];
preSum[0]= nums[0];for(int i =1; i < preSum.length; i++){
preSum[i]= preSum[i -1]+ nums[i];}int res =0;// 前缀和 -> 该前缀和出现的次数HashMap<Integer,Integer> map =newHashMap<>();
map.put(0,1);for(int i =0; i < preSum.length; i++){if(map.containsKey(preSum[i]- k)){
res += map.get(preSum[i]- k);}
map.put(preSum[i], map.getOrDefault(preSum[i],0)+1);}return res;}}
974. 和可被 K 整除的子数组
/*
(preSum[i] − preSum[j]) mod k == 0
⟺ preSum[i] mod k == preSum[j] mod k
*/classSolution{publicintsubarraysDivByK(int[] nums,int k){// 前 i 个数中奇数的个数int[] preSum =newint[nums.length];
preSum[0]= nums[0];for(int i =1; i < preSum.length; i++){
preSum[i]= preSum[i -1]+ nums[i];}int res =0;// 前缀和对 k 的余数 -> 该前缀和出现的次数HashMap<Integer,Integer> map =newHashMap<>();
map.put(0,1);for(int i =0; i < preSum.length; i++){// 当被除数为负数时取模结果为负数,需要将负数转为对应的正数// 比如:-7 % 3 = -1,-7 mod 3 = 2int mod =(preSum[i]% k + k)% k;if(map.containsKey(mod)){
res += map.get(mod);}
map.put(mod, map.getOrDefault(mod,0)+1);}return res;}}
523. 连续的子数组和
/*
(preSum[i] − preSum[j]) mod k == 0
⟺ preSum[i] mod k == preSum[j] mod k
当两个不同位置的前缀和对 k 的取余相同时,我们看这两个位置下标距离是否大于等于 2。如果满足以上条件,那么我们就找到了长度至少为 2 并且总和是 k 的倍数的连续数组
*/classSolution{publicbooleancheckSubarraySum(int[] nums,int k){int[] preSum =newint[nums.length];
preSum[0]= nums[0];for(int i =1; i < preSum.length; i++){
preSum[i]= nums[i]+ preSum[i -1];}// 前缀和对 k 的余数 -> 该前缀和对应的下标HashMap<Integer,Integer> map =newHashMap<>();// 必须有下面这行代码。如果单个前缀和就已经可以整除 k 了,那么其对 k 的余数就为 0,然后我们需要判断其下标是否符合要求。如果第一个前缀和(preSum[0])就可以整除 k,那么其子数组长度就为 1,不符合要求,所以我们需要将 value 初始化为 -1 来排除这种情况(比如 nums = [6,1], k = 6),而 nums = [3,4], k = 7 这种就符合要求
map.put(0,-1);for(int i =0; i < preSum.length; i++){int mod = preSum[i]% k;if(map.containsKey(mod)){if(i - map.get(mod)>=2){returntrue;}}else{
map.put(mod, i);}}returnfalse;}}
525. 连续数组
classSolution{publicintfindMaxLength(int[] nums){// 求前缀和数组。遇到 0 则减一,遇到 1 则加一int[] preSum =newint[nums.length];
preSum[0]= nums[0]==0?-1:1;for(int i =1; i < nums.length; i++){if(nums[i]==0){
preSum[i]= preSum[i -1]-1;}else{
preSum[i]= preSum[i -1]+1;}}int res =0;// 前缀和 -> 该前缀和对应的下标Map<Integer,Integer> map =newHashMap<>();
map.put(0,-1);for(int i =0; i < preSum.length; i++){if(map.containsKey(preSum[i])){
res =Math.max(res, i - map.get(preSum[i]));}else{
map.put(preSum[i], i);}}return res;}}
1248. 统计「优美子数组」
classSolution{publicintnumberOfSubarrays(int[] nums,int k){// 前 i 个数中奇数的个数int[] preSum =newint[nums.length];
preSum[0]= nums[0]%2==1?1:0;for(int i =1; i < preSum.length; i++){if(nums[i]%2==1){
preSum[i]= preSum[i -1]+1;}else{
preSum[i]= preSum[i -1];}}int res =0;// 前缀和 -> 该前缀和出现的次数(前缀和中保存的是前i个数中奇数的个数)HashMap<Integer,Integer> map =newHashMap<>();
map.put(0,1);for(int i =0; i < preSum.length; i++){if(map.containsKey(preSum[i]- k)){
res += map.get(preSum[i]- k);}
map.put(preSum[i], map.getOrDefault(preSum[i],0)+1);}return res;}}