这道题依然是不会啊,去看了灵神的题解才做出来的,这里讲一下详细的思路。
为了降低运算的次数和时间复杂度,我们需要定义一个数组pre
来存储前缀和,对于数组元素pre[j]
,其定义为从nums[0]
到nums[j - 1]
的所有元素之和,其中,pre[0] = 0
。首先我们定义一个大小为nums.size() + 1
的前缀和数组pre
,先遍历一遍nums
,将pre
统计出来。然后再来看题意,题目要求和为k的连续子数组的个数,我们只需要找到这样一对(i,j)
(j > i),使得pre[j] - pre[i] = k
即可,然后我们再将符合条件的(i,j)
的个数统计出来并返回即可。将等式左右移项,可以得到pre[i] = pre[j] - k
,所以我们在遍历pre
数组的时候,只需要统计pre
数组中每一个pre[j]
左侧的pre[j] - k
的个数即可(必须是左侧的,不包含自己),然后将对应的结果累加到result中,pre[j] - k
的个数我们用哈希表来统计。注意!!!在代码实现中,需要先将每一个pre[j]
左侧的pre[j] - k
的个数累加到result中,再将当前遍历到的pre[j]
加入到哈希表中,顺序不能颠倒,否则可能会出现自己被加到结果中(k = 0)的情况。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int result = 0;
vector<int> pre(nums.size() + 1, 0); //前缀和数组
unordered_map<int, int> hash; //哈希表,用于存储每一个前缀表中的值的个数
for(int i = 1; i < pre.size(); i++)
pre[i] = pre[i - 1] + nums[i - 1];
for(int i = 0; i < pre.size(); i++){ //必须要从0开始,而不是从1开始,从零开始主要是为了执行hash[pre[i]]++;
result += hash.contains(pre[i] - k) ? hash[pre[i] - k] : 0;
hash[pre[i]]++;
}
return result;
}
};
这道题必须要反复刷