和为K的子数组 - 前缀和+哈希表
1. 题目描述
给定一个整数数组和一个整数k
,你需要找到该数组中和为k
的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
2. 题解
public int subarraySum(int[] nums, int k) {
int count = 0, pre = 0;
HashMap < Integer, Integer > mp = new HashMap < > ();
mp.put(0, 1);
for (int i = 0; i < nums.length; i++) {
pre += nums[i];
if (mp.containsKey(pre - k)) {
count += mp.get(pre - k);
}
mp.put(pre, mp.getOrDefault(pre, 0) + 1);
}
return count;
}
我们定义pre[i]
为[0...i]
里所有数的和。
假设和为k
的子数组下标范围为[j...i]
,于是pre[i] - k = pre[j - 1]
。
示例:nums = [3, 4, 7, 2, -3, 1, 4, 2], k = 7
遍历到nums[1]
时,哈希表mp
为{0=1, 3=1, 7=1}
,pre[1] - 7 = 0
,哈希表中存在键0
。
遍历到nums[2]
时,哈希表mp
为{0=1, 3=1, 7=1, 14=1}
,pre[2] - 7 = 7
,哈希表中存在键7
。
遍历到nums[5]
时,哈希表mp
为{0=1, 16=1, 3=1, 7=1, 13=1, 14=2}
,pre[5] - 7 = 7
,哈希表中存在键7
。
遍历到nums[7]
时,哈希表mp
为{0=1, 16=1, 18=1, 3=1, 20=1, 7=1, 13=1, 14=2}
,pre[7] - 7 = 13
,哈希表中存在键13
。
最后,和为k
的连续的子数组的个数为4
。
示例:nums = [3, 4, 7, 2, -3, 1, 4, 2, 1], k = 7
遍历到nums[8]
时,哈希表mp
为{0=1, 16=1, 18=1, 3=1, 20=1, 21=1, 7=1, 13=1, 14=2}
,pre[8] - 7 = 14
,哈希表中存在键14
。
最后,和为k
的连续的子数组的个数为6
。
符合条件的子数组个数多了两个,分别为[2, -3, 1, 4, 2, 1]
和[4, 2, 1]
。
哈希表中mp
中14=2
表示前缀和为14
的子数组出现了两次,这两个子数组分别为[3, 4, 7]
和[3, 4, 7, 2, -3, 1]
。
参考: