给你一个整数数组 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;
- }
- };