首先写一个最暴力的算法
int subarraySum(vector<int>& nums, int k) {
int n=nums.size();
int ans=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int sm=0;
for(int k=i;k<=j;k++){
sm+=nums[k];
}
ans+=sm==k;
}
}
return ans;
}
注意到求和部分可以用前缀和优化
int subarraySum(vector<int>& nums, int k) {
int n=nums.size();
int ans=0;
nums.insert(nums.begin(),0);
for(int i=1;i<=n;i++)
pre[i]=nums[i]+pre[i-1];
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
int sm=pre[j]-pre[i-1];
ans+=sm==k;
}
}
return ans;
}
再观察题目,猛然发现,这不就是检查pre数组中满足 差为 k的元素对数吗?
设i,j是pre中两个下标 , k== pre[j]-pre[i-1]
变化为 k+pre[i-1]==pre[j]
,注意到上边的循环是始终满足j>=i
的,因此我们在想要求得pre[j]
对应的对数时,不应该和所有的i进行比较,应该和 小于
j的i进行比较, 因此,我们在 进行j 循环的第一步, 就记录前缀和到map里去
int subarraySum(vector<int>& nums, int k) {
int n=nums.size();
int ans=0;
nums.insert(nums.begin(),0);
unordered_map<int,int> mp;
for(int i=1;i<=n;i++)
pre[i]=nums[i]+pre[i-1];
for(int j=1;j<=n;j++){
mp[pre[j-1]+k]++;
ans+=mp[pre[j]];
}
return ans;
}