Bootstrap

和为 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

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> m;
        m[0]=1;
        int s,ans=0;
        for(int n:nums){
            s += n;
            if(m.find(s-k) != m.end()){
                ans+=m[s-k];
            }
            m[s]++;
        }
        return ans;
    }
};

如果有两个前缀和 sum(i)sum(j),那么sum(j) - sum(i) = k则表示子数组从 i+1j 的和为 k

哈希表 m 来记录每个前缀和的出现次数。

m[0] = 1 是为了处理一种特殊情况:假设从数组的第一个元素开始就有子数组和为 k

对于每一个前缀和 s,我们检查哈希表 m 中是否存在 s - k 这个值。

对于每个新出现的 sum(j),我们检查是否有一个 sum(i) 使得 sum(j) - sum(i) = k,即 sum(j) - k 是否已经出现过。如果出现过,说明从某个位置到当前位置的子数组和为 k,我们就能增加结果计数。

实例:

nums = [1, 2, 3], k = 3

  • 初始化:m = {0: 1}, s = 0, ans = 0

  • 第一次迭代 (i = 0, num = 1):

    • s = 0 + 1 = 1
    • 查找 s - k = 1 - 3 = -2,没有找到。
    • 更新哈希表:m = {0: 1, 1: 1}
  • 第二次迭代 (i = 1, num = 2):

    • s = 1 + 2 = 3
    • 查找 s - k = 3 - 3 = 0,找到了,m[0] = 1,所以 ans += 1
    • 更新哈希表:m = {0: 1, 1: 1, 3: 1}
  • 第三次迭代 (i = 2, num = 3):

    • s = 3 + 3 = 6
    • 查找 s - k = 6 - 3 = 3,找到了,m[3] = 1,所以 ans += 1
    • 更新哈希表:m = {0: 1, 1: 1, 3: 1, 6: 1}

最终结果:ans = 2,表示有 2 个子数组和为 3,分别是 [1, 2][3]

;