题目:
给你一个整数数组 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
算法原理:
求和为k的连续子数组个数,可能你会想到利用滑动窗口解题,但解决不了,因为该题目中找不到单调性,元素有负数和0,而且滑动窗口解题会漏掉一些合法的子数组个数,比如
暴力枚举所有子数组的方法是每次固定一个起始位置,开始向后枚举子数组
那么我们也可以每次固定一个结尾位置,开始向前枚举子数组
这里的i是任意一个位置,要找以i位置为结尾且和为k的子数组有多少个,即可转化为:
求[0,i-1]区间内前缀和为sum-k的个数
hash表统计前缀和出现的次数
细节:hash[0]=1 当i位置的前缀和sum本身就等于k时,sum-k=0
代码实现:
class Solution
{
public:
int subarraySum(vector<int>& nums, int k)
{
unordered_map<int,int> hash;//统计前缀和出现的次数
hash[0] = 1;
int ret = 0;
int sum = 0;
for(auto e:nums)
{
sum+=e;//计算当前位置的前缀和,当前位置的前缀和=前一个位置的前缀和+当前元素
if(hash.count(sum-k))
{
ret+=hash[sum-k];
}
hash[sum]++;
}
return ret;
}
};