图解题库 / 前缀和 · 哈希

560. 和为 K 的子数组

中等 含交互动画

学完这道你应该能: 说清它为什么用「哈希」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

给整数数组 nums 和整数 k,求连续子数组的和等于 k 的个数(数组可能含负数)。

nums = [1, 2, 3]
k = 3
输出 = 2([1,2] 和 [3])

思路解析

双重循环把每段都加一遍能做,可一旦数据量大就吃力,而且没利用上「前缀和之差」这个巧劲。

记 pre 为从头加到当前的累加和。一段 (i, j] 的和等于 pre[j] − pre[i]。要它等于 k,就是找「前面有多少个 pre[i] 正好等于 pre[j] − k」。

边走边把出现过的前缀和计数存进哈希表。到每个位置,查一下 pre − k 出现过几次,就知道有几段以这里结尾、和为 k。初始要放一个 {0: 1}。

初始化:开局先往哈希表塞一个 {0:1}。它代表「啥都没加」的前缀和 0——这是为了能数到「从头开始那一段」。

i=0, 值 1:加到 1,前缀和 pre=1。查 1−3=−2 在不在表里——不在,没有合格子数组。然后把 pre=1 记进哈希表。

i=1, 值 2:加到 2,pre=3。查 3−3=0,表里有 1 个 0!说明从某处到这里和正好是 3——正是 [1,2]。count 加 1。

i=2, 值 3:加到 3,pre=6。查 6−3=3,表里有 1 个 3!对应子数组 [3],count 再加 1。扫完,答案是 2

「连续子数组求和/计数」的通杀套路:把区间和转成前缀和之差,再用哈希表 O(1) 查有没有需要的那个前缀和

参考代码(Python)

Python
1def subarraySum(nums, k):
2    from collections import defaultdict
3    seen = defaultdict(int); seen[0] = 1     # 关键:和为 0 出现 1
4    pre = 0; count = 0
5    for x in nums:
6        pre += x
7        count += seen[pre - k]               # 先查:有几个前缀和 = pre-k
8        seen[pre] += 1                       # 后记:把当前前缀和计数
9    return count

复杂度分析

  • 时间复杂度:O(n) —— 一遍扫描
  • 空间复杂度:O(n) —— 哈希表存前缀和

套路模板

骨架就这几行。两个铁律:哈希表初始化 {0:1}、先查 pre−k 再记 pre。顺序反了答案就错。

Python
1seen = {0: 1}        # 别忘了这一项
2pre = count = 0
3for x in nums:
4    pre += x
5    count += seen.get(pre - k, 0)   # 先查
6    seen[pre] = seen.get(pre, 0) + 1 # 后记

易错点

  • 忘了初始化 seen = {0: 1} → ✅ 一开始就放 {0: 1}(少了它,「从下标 0 开头、整段和为 k」的情况会被漏掉)
  • 查 k − pre → ✅ 查 pre − k(区间和 = pre[j] − pre[i] = k,所以要找的是 pre[i] = pre[j] − k)
  • 先记 pre 再查(顺序反了) → ✅ 先查 pre−k,再记 pre(反了会把当前这个前缀和也算进候选,凭空多算)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →22. 括号生成 ← 返回题库