[LeetCode 560.] Subarray Sum Equals K
LeetCode 560. Subarray Sum Equals K
题目描述
Given an array of integers nums and an integer k, return the total number of continuous subarrays whose sum equals to k.
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
解题思路
这道题是说给出一个数组,查找出有多少个连续切片的元素之和为k。
有了“元素和”这个关键信息之后,我们自然会想到前缀和,求切片和只需要两个前缀和相减就可以了。
要统计满足要求的切片,暴力检索并不是一个好办法。这里我们考虑枚举切片的结束位置,查找满足要求的开始位置。
这里我们可以考虑使用一个哈希表来存储前缀和与数组下标的对应关系。
参考代码
注意到本题的元素个数和取值范围,可以保证前缀和不会超出 int 取值范围。
第一个解存储了前缀和对应的数组下标,可以在统计切片个数的同时给出对应切片。
但这不是必要的,本题需要的只是前缀和对应切片个数,因此第二个解只是统计前缀和对应数组下标的个数。这里利用了 C++ 的 unordered_map 中类似 Java 中 getOrDefault 的功能,不存在的 int 类型 value 返回 0。
/*
* @lc app=leetcode id=560 lang=cpp
*
* [560] Subarray Sum Equals K
*/
// @lc code=start
class Solution {
public:
/*
int subarraySum(vector<int>& nums, int k) {
int cnt = 0;
unordered_map<int, vector<int>> hash;
int acc = 0; // assert(acc <= 2 * 10^6)
hash[0].push_back(-1);
for (int i=0; i<nums.size(); i++) {
acc += nums[i];
cnt += hash[acc - k].size();
hash[acc].push_back(i);
}
return cnt;
} // AC
*/
int subarraySum(vector<int>& nums, int k) {
int cnt = 0;
unordered_map<int, int> hash;
int acc = 0; // assert(acc <= 2 * 10^6)
hash[0] = 1;
for (int i=0; i<nums.size(); i++) {
acc += nums[i];
cnt += hash[acc - k];
hash[acc] ++;
}
return cnt;
} // AC
};
// @lc code=end