这个题一看就是前缀和,但是前缀和加暴力需要
O
(
N
2
)
O(N^2)
O(N2)的时间。
在此题中,我们求的是子数组的个数,无需考虑构成,所以可以采用一种历史前缀和的形式,不必每次都遍历之前的,可以有效减少重复计算。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
vector<int> presum{0};
for(auto num: nums)presum.push_back(num+presum.back());
unordered_map<int, int> m;
int ans = 0;
for(auto sum: presum)
{
if(m.count(sum))ans += m[sum];
m[sum+k]++;
}
return ans;
}
};
再想想其实我们还可以再优化的,因为只用到了前缀和历史,所以其实不用存前缀和数组了,O(1)就直接完事,一边算一边做。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int ans = 0, sum = 0;
unordered_map<int, int> m;
m[k] = 1;
for(auto num: nums)
{
sum += num;
if(m.count(sum))ans += m[sum];
m[sum+k]++;
}
return ans;
}
};