给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况
示例 2 :
输入:nums = [1,2,3], k = 3
输出: 2
提示:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/QTMn0o
题解:
乍一看,以为是滑动窗口的题,直接暴力,但是数据里面有复数,而滑动窗口要求均为整数
这里要用前缀和+hash map
时间复杂度过高是因为,使用了一个循环去求解 sum[i] - sum[j - 1] = k 的结果,这个过程消耗的时间复杂度为 O(n)。对 sum[i] - sum[j - 1] = k 做下变形为 sum[j - 1] = sum[i] - k,所以这个循环要找的就是 sum[j - 1] = sum[i] - k 的个数。这个过程使用哈希表就可以将时间复杂度由 O(n) 降为 O(1),因为当前的 sum[i] 是已知计算得到的,而 sum[j - 1] 也只不过是之前计算得到的 sum 而已,若设置哈希表的键为前缀和 sum[i],值为每个和出现的次数,那么就可以做到优化。
res+=ma[now-k]>0?ma[now-k]:0; //判断前缀差为K 是否存在,存在则加上。不存在加0.
1 class Solution { 2 public: 3 int subarraySum(vector<int>& nums, int k) { 4 map<int,int> ma; 5 int n=nums.size(),res=0,now=0; 6 ma[0]=1; 7 for(int i=0;i<n;i++) 8 { 9 now+=nums[i]; 10 res+=ma[now-k]>0?ma[now-k]:0;//用于找是否存在前缀和的差是k的数 11 ma[now]>0?ma[now]++:ma[now]=1; //存前缀和 12 } 13 return res; 14 } 15 };