-
给你一个整数数组
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
1.解题思路,由于子数组是数组中元素的连续非空序列,所以创建一个数组,存入前缀和表,
前缀和表第一个数字要设置为0,要比正常表多一位,下面进行假设
-
nums有6个数字分别为 1,1,0,-2,4,1
那么前缀和表就是 0,1,2,2,0,4,5
当前前缀和减去k(比如是2),所得到的数,可以列一个表
对应得到的差值表 0,-1, 0, 0,-2, 2, 3
这个表的数字
比如第三个0,对应前缀和表的第一个0,就可以得到前面有数字相加等于2,分别是nums第一个1和第二个1
比如第四个0,还是对应前缀和表的第一个0,就可以得到前面有数字相加等于2,分别是第一个1和第二个1和第三个0
比如第五个0,对应前缀和表的第三个和第四个2,就可以得到前面有数字相加等于2,分别是0,2,-4,和 2,-4
但是如果nums和k全为0呢,那不就是前面的任意组合都是0么,所以我们需要定义一个hash表,记录前面前缀和出现的个数
直接写出来
class Solution {
public int subarraySum(int[] nums, int k) {
int[] prefixSum = new int[nums.length+1]; //前缀和表比nums数组大一位
prefixSum[0] = 0; //第一位为0
for (int i = 0; i < nums.length; i++) { //直接算出前缀和表
prefixSum[i + 1] = prefixSum[i] + nums[i]; //i+1的值,等于前面的和与当前数字相加
}
int sum = 0 ;
Map<Integer, Integer>map= new HashMap<>();
for(int i=0 ;i<prefixSum.length;i++){ //这里是遍历的前缀和表
sum = sum + map.getOrDefault(prefixSum[i]-k,0); // 如果表里有与当前prefixSum[i]-k的差相等,则加上它的个数
//考虑的是全为0的情况,那不就是前面的任意组合都是0么
map.put(prefixSum[i] , map.getOrDefault(prefixSum[i],0)+1 ); //添加进表,前面是值,后面是个数
}
return sum; //返回
}
}