题目:给定一个整数数组和一个整数 k
,请找到该数组中和为 k
的连续子数组的个数。
输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况
本题采用前缀和+哈希表来实现,时间复杂度O(n)
还可以使用暴力法来解决,但是时间复杂度为O(N^2),会超出时间限制
//前缀和+哈希表
此时哈希表的key值表示[0-i]中所有元素之和pre
需要求解的是,以i为结尾的,**前缀和[i] - 前缀和[j] = k** 的个数 移项得,**前缀和[j] = 前缀和[i] - k**
value值表示的是pre出现的次数
前缀和[i]已经在遍历的时候用变量pre表示了,k也是已知的,那就可以根据公式求得**前缀和[j]**的数值,再根据map查找此数值出现的次数,最后相加就是结果。
源代码如下:
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count=0;//存储符合条件的子数组的个数
int pre=0;//前i个元素之和
int n=nums.size();//数组长度
unordered_map<int,int> map;//定义一个哈希表
map[0]=1;//初始化,因为存在nums[i]=k的情况
for(int i=0;i<n;i++)
{
pre+=nums[i];//不断累加nums[i]
//在哈希表中查找pre[j-1]=pre[i]+k是否存在
//如果不等于map.end()说明找到了
//遍历顺序是从前往后遍历,再逐个对前缀和进行存储,也就保证了find找到的下标j在下标i前面的条件。
if(map.find(pre-k)!=map.end())
{
//找到了说明这个子数组符合条件
//那么就给count加上[pre-k]出现的次数
count+=map[pre-k];
}
map[pre]++;//给map[pre]++,说明以i结尾的这个元素使用次数+1
}
//返回count
return count;
}
};