剑指 Offer II 010. 和为 k 的子数组

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

 

posted @ 2021-12-21 16:34  sylvia11  阅读(41)  评论(0编辑  收藏  举报