560 和为K的子数组
解题思路:
最先向想到的是三重暴力循环:如下代码所示:时间复杂度为O(n^3);超时
int subarraySum(vector<int>& nums, int k) {
int cnt=0;
for(int i = 0; i<nums.size();i++){
for(int j=i;j<nums.size();j++){
int sum = 0;
for(int k=i;k<=j;k++){
sum += nums[k];
}
if(sum == k) cnt++;
}
}
return cnt;
}
然后是优化后的暴力解法
int cnt = 0;
int len = nums.size();
for(int i=0;i<len;i++){
int sum=0;
for(int j = i;j < len;j++){
sum+=nums[j];
if(sum==k) cnt++;
}
}
return cnt;
最后是利用前缀和加上哈希表
求j到i的和为k的子数组,等价于求到i的前缀和为pre-k的数组个数;对数组遍历一遍,记录每个前缀和出现的次数,从前往后,如果出现多次,每次累加一即可;
unordered_map<int,int>mp;
//和为键,出现次数为值
mp[0]=1;
int cnt=0;
int pre=0;
for(auto num:nums){
pre+=num;
if(mp.find(pre-k)!=mp.end()){
cnt+=mp[pre-k];
}
mp[pre]++;;
}
return cnt;