思路:
(1)暴力法:时间复杂度o(n^3)
(2)优化后的暴力法:时间复杂度o(n^2)
(3)累加数组数字:时间复杂度o(n)
(1)暴力法
时间复杂度太高了,运行超时了。
class Solution {
public:
int subarraySum(vector<int>& nums, int k)
{
int res = 0;
for (int i = 0;i < nums.size();i++)
{
int sum = 0;
sum += nums[i];
if (sum == k)
res++;
for (int j = i + 1;j < nums.size();j++)
{
sum += nums[j];
if (sum == k)
{
res++;
}
}
}
return res;
}
};
(3)累加数组和
因为本题是求连续子数组,我们用前缀和去做,遍历一次数据,将前N个数字的和作为key保存在哈希表里面,如果有重复则value+1。
当我们遍历的时候出现前N项和减去目标值在哈希表里面的时候,就表示有符合的子串,这里是最难以理解的地方。
让哈希表的第一个键为(0,1)也很重要,这表示刚好我们遍历的第N个数的前N项和就是等于k的。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> ump;
ump[0] = 1; // 表示以nums[i]结尾的序列和正好是k的情况
int preSum = 0;
int result = 0;
for (int i = 0; i < nums.size(); i++) {
preSum += nums[i];
if (ump.count(preSum - k) != 0) { // 查找一下之前记录的前缀和中是否出现过preSum[i] - k,肯定是往前找
result += ump[preSum - k];
}
ump[preSum]++; // 不断更新哈希表中前缀和的情况
}
return result;
}
};