560.Subarray Sum Equals K

25 年 7 月 12 日 星期六
814 字
5 分钟

560. Subarray Sum Equals K

Screenshot 2026-03-08 at 10.53.10 pm

我们可以一边计算前缀和,一边遍历前缀和。

在遍历 nums 之前,我们需要先统计 s[0]=0,即空前缀的元素和等于 0。往 cnt 中添加 cnt[0]=1。

js
var subarraySum = function (nums, k) {
  const cnt = new Map()
  cnt.set(0, 1) // s[0]=0 单独统计
  let ans = 0,
    s = 0
  for (const x of nums) {
    s += x
    ans += cnt.get(s - k) ?? 0
    cnt.set(s, (cnt.get(s) ?? 0) + 1)
  }
  return ans
}
js
/**
 * 计算数组中和为k的子数组的个数
 * @param {number[]} nums - 输入的整数数组(可包含正负整数)
 * @param {number} k - 目标子数组和
 * @returns {number} - 和为k的子数组的总个数
 * 算法思路:前缀和 + 哈希表(Map)优化,时间复杂度O(n),空间复杂度O(n)
 */
var subarraySum = function (nums, k) {
  // 1. 初始化哈希表,用于存储前缀和出现的次数
  // 键:前缀和的值,值:该前缀和出现的次数
  const prefixSumCount = new Map()

  // 2. 初始化结果计数器和当前前缀和
  let result = 0 // 记录和为k的子数组总数
  let currentSum = 0 // 记录遍历过程中累加的前缀和

  // 3. 遍历数组中的每个元素
  for (const num of nums) {
    // 3.1 先将当前的前缀和(未加当前num前)存入哈希表
    // 如果该前缀和已存在,次数+1;不存在则初始化为1
    prefixSumCount.set(currentSum, (prefixSumCount.get(currentSum) ?? 0) + 1)

    // 3.2 累加当前元素,更新前缀和
    currentSum += num

    // 3.3 核心逻辑:查找是否存在前缀和 = currentSum - k
    // 如果存在,说明这两个前缀和之间的子数组和为k,次数累加到结果中
    // ?? 0 处理前缀和不存在的情况(此时贡献0次)
    result += prefixSumCount.get(currentSum - k) ?? 0
  }

  // 4. 返回最终统计的子数组个数
  return result
}

要统计的是「当前位置之前的前缀和」(j < i),因此必须先把更新前的前缀和(代表「之前的状态」)存入哈希表,再更新前缀和。

初始值作用:哈希表初始存入 {0:1} 是为了处理「从数组第一个元素开始的子数组」(比如示例中的 [3]),确保这类情况能被正确统计。

我们可以一边计算前缀和,一边遍历前缀和。

在遍历 nums 之前,我们需要先统计 s[0]=0,即空前缀的元素和等于 0。往 cnt 中添加 cnt[0]=1。

在同一轮循环中,先把 s[i−1] 加入哈希表,再根据 s[i] 更新答案。

这样写无需初始化 cnt[0]=1。

js
var subarraySum = function (nums, k) {
  const cnt = new Map()
  let ans = 0,
    s = 0
  for (const x of nums) {
    cnt.set(s, (cnt.get(s) ?? 0) + 1)
    s += x
    ans += cnt.get(s - k) ?? 0
  }
  return ans
}
  • 你现在走到了数组的第 i 步,手里的总钱数是 s(当前前缀和);
  • 你想知道 “从哪一步开始,到现在赚了 k 块钱”;
  • 那只需要看 “之前有没有哪一步,手里的钱数是 s - k”—— 如果有,说明从那一步到现在,刚好赚了 k 块;
  • cnt 就是记录 “之前每一步手里有多少钱、出现过多少次” 的账本,查 s-k 就是翻账本找对应的记录。

文章标题:560.Subarray Sum Equals K

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/560subarray_sum_equals_k[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。