https://leetcode.cn/problems/subarray-sum-equals-k/?envType=study-plan-v2&envId=top-100-liked
1. 用到了前缀和的概念:
给定一个数组nums,从该数组的初始位置元素开始相加,前缀和数组 prefixSum
的第 i
个元素表示从数组开头到第 i
个位置的元素之和。
对于数组 nums = [1, 2, 3, 4, 5]
,其前缀和数组 prefixSum
为 [1, 3, 6, 10, 15]
。其中,prefixSum[i]
表示数组 nums
中前 i+1
个元素的和。
2. 思路原理
(1) 为啥要计算前缀和?
当前缀和>target时,如果在前缀和中还存在“前缀和-target”,就说明数组中存在一截连续部分的和等于target
(2) 看看有几个符合要求的前缀和
total += 符合要求的前缀和的数量
(3)先判断还是先添加
假设我们的数组为 nums = [3, 4, 7, 2]
,目标值为 k = 7
。我们用哈希表记录前缀和出现的次数。
- 首先,初始化前缀和哈希表,包含一个前缀和为 0 的情况:
Prefix.put(0, 1)
。 - 遍历到第一个元素 3 时,前缀和为 3,将其添加到哈希表中,哈希表为
{0: 1, 3: 1}
。 - 遍历到第二个元素 4 时,前缀和为 3 + 4 = 7。此时我们检查哈希表中是否存在前缀和为 7 - 7 = 0,即是否存在以当前位置为结尾的子数组的和等于目标值 k。由于哈希表中存在前缀和为 0,我们将之前统计的子数组个数累加到结果中。然后,我们将当前前缀和 7 添加到哈希表中,哈希表为
{0: 1, 3: 1, 7: 1}
。 - 继续遍历数组,遍历到第三个元素 7 时,前缀和为 3 + 4 + 7 = 14。我们检查哈希表中是否存在前缀和为 14 - 7 = 7,即是否存在以当前位置为结尾的子数组的和等于目标值 k。由于哈希表中存在前缀和为 7,说明存在一个满足条件的子数组,我们将之前统计的子数组个数累加到结果中。
这样的例子说明了为什么在计算前缀和之前要先判断是否存在 sum - k
这样的前缀和,然后再将当前前缀和添加到哈希表中。这样能够保证正确地统计子数组的个数,避免出现错误的情况。
3. 完整代码
class Solution {
public int subarraySum(int[] nums, int k) {
int res = 0;
int sum = 0;
Map<Integer, Integer> Prefix = new HashMap<>();
// 前缀和的初始化,key表示前缀和的值,value表示满足这个值的前缀和的个数
Prefix.put(0,1);
for(int i=0; i<nums.length; ++i){
sum += nums[i];
if(Prefix.containsKey(sum - k)){
res += Prefix.get(sum-k);
}
// 得先判断前缀和map里是否已经存在了sum-k
// 再添加新的sum
Prefix.put(sum, Prefix.getOrDefault(sum,0)+1);
}
return res;
}
}