Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [1, 1, 1], k = 2
Output: 2
Example 2:
Input: nums = [1, 2, 3], k = 3
Output: 2
Constraints:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107
分析
前缀和 + 哈希表
前缀和,就是从数组0号元素开始,到当前元素的,所有元素的数值总和。
mp[presum]
表示 当前 数组元素之前,前缀和 为presum的子数组的 个数。
图示
若所求K = 0:
遍历到每一个元素,都检查一遍有多少个符合条件的前缀和,然后再把当前前缀和添加到哈希表中,我们只要符合条件的数量,不要求具体是哪一个子数组,所以这样最快。
时间、空间复杂度都是
O
(
n
)
O(n)
O(n)。
代码
#include <unordered_map>
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
mp[0] = 1; // 这一步很重要,表示在0号元素之前,有 1 个前缀和为 0 的子数组
int sum = 0;
int count = 0;
for (int item: nums) {
sum += item;
int presum = sum - k; // sum - presum == k的等价变换
// 存在为mp[presum] 不存在为 0
int pre_num = mp.count(presum) ? mp[presum] : 0; // 看有多少个符合条件的子数组
// 这些子数组都是从0开始的前缀子数组
// 所以,当前前缀和,减去之前的 符合条件的 前缀和的 数量,就是count要加上的
count += pre_num;
// 对于当前前缀和,存在加 1,不存在赋值 1
mp[sum] = mp.count(sum) ? (mp[sum] + 1) : 1;
}
return count;
}
};