给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107*/
思路:
本来想用滑动窗口实现,但是实现后发现,该方法只对数组元素全部为正才能用,
题目中是整数数组,整数包括负整数和正整数和0,当有负整数时,和不是越加越大
所以不能使用滑动窗口实现
该问题是一个前缀和的典型问题
前缀和问题就是用 sum[i] - sum[j] 快速计算数组 [j ,i] 元素和的问题。详细来说,就是通过预处理计算出以第 0 个元素起始,到第 i 个元素结尾的元素之和,并将其记录为数组 sum,从而实现通过 sum[i] - sum[j] 快速计算 [j ,i] 位置的元素和,这样的问题就是前缀和问题
例如[0,1,2,3,5,6,-1,-2],前缀和为[0,1,3,6,11,17,16,14]
那么上述问题可以改为sum[i]-sum[j]=k,再次转换可以转换为,nums[i]-k=nums[j]的问题
有多少个nums[j]=nums[i]-k,就是有多少个符合和为k的子数组
public static int getNumber(int[] nums ,int k){
//次数
int count =0;
//和
int sum=0;
//记录前缀和一样的前缀和数量
HashMap<Integer,Integer> hashMap = new HashMap<>();
hashMap.put(0,1);//和为0的默认次数为1;
for (int i = 0; i < nums.length; i++) {
sum+=nums[i];//前缀和
count+=hashMap.getOrDefault(sum-k,0);//当map中有符和条件的前缀和时,次数增加
//没有的话就是0
hashMap.put(sum,hashMap.getOrDefault(sum,0)+1);//将前缀和相同的放入map,已经放入的就次数加1
}
return count;
}