Day22[26/3/22]T560和为k的子数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
1 <= nums.length <= 2 * 104-1000 <= nums[i] <= 1000-107 <= k <= 107
解题思路
采用前缀和+哈希表解决
前缀和可以很轻松的求取某一个区间的和,比如说,你想求取 nums[i...j] 的和,那么就可以用 prefix_sum[j + 1] - prefix_sum[i] 来算。然后前缀和也很容易实现,就是循环 nums[i] += nums[i - 1] 就可以把原来的数组变成前缀和了。
哈希表则是查找元素的速度极快,复杂度是 O(1)。
所以可以一边计算前缀和,然后一边查找,当前前缀和减去目标值之后,这个数字存不存在,存在的话,有几个,这样就可以统计,以当前元素为结尾时,和为 k 的字串的个数了。
然后有一个小细节,就是,你得考虑从第一个元素开始统计的字串,你得怎么计算,得要减去 0,所以初始化哈希表的时候,需要放入{0 , 1}.
Code
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution
{
public:
int subarraySum(vector<int> &nums, int k)
{
unordered_map<int, int> mp{
{0, 1}};
int count = 0;
// 对于[0]元素要特别处理
if (nums[0] == k)
{
count++;
}
if (nums[0] == 0)
{
mp[0]++;
}
else
{
mp[nums[0]] = 1;
}
for (int i = 1; i < nums.size(); i++)
{
// 1. 先求取前缀和
nums[i] += nums[i - 1];
// 2. 然后看有无区间存在
if (mp.count(nums[i] - k))
{
count += mp[nums[i] - k];
}
// 3. 最后要记得把本次前缀和写入哈希表
if (mp.count(nums[i]))
{
mp[nums[i]]++;
}
else
{
mp[nums[i]] = 1;
}
}
return count;
}
};
auto main() -> int
{
Solution sol;
vector<int> nums{1, 2, 3};
int k = 3;
cout << "result = " << sol.subarraySum(nums, k) << endl;
}