#560
中等
低频
前缀和和为K的子数组
这是一道围绕数组展开的高频练习。建议先掌握「前缀和」这套写法,再结合下方步骤讲解理解状态维护、边界处理和复杂度取舍。
数组
题目分析
给你一个整数数组和一个整数 k,要求统计有多少个连续子数组的和正好等于 k。
这里不是只找一个,而是要统计所有满足条件的区间个数。
一句话概括:
把区间和转成两个前缀和之差,再统计这种差值出现了多少次。
接下来怎么看推荐代码: 带着这个理解再看推荐代码时,重点观察这条主线:遍历数组时维护前缀和,并用哈希表统计每个前缀和出现次数,查询
sum-k 就知道有多少个区间以当前位置结尾。推荐代码
推荐解法:前缀和
时间复杂度: O(n)
空间复杂度: O(n)
核心思路: 遍历数组时维护前缀和,并用哈希表统计每个前缀和出现次数,查询
sum-k 就知道有多少个区间以当前位置结尾。// 和为K的子数组 - Java实现
// 算法:前缀和 + 哈希表
import java.util.HashMap;
public class Solution {
/**
* 计算和为k的子数组个数
* @param nums 输入数组
* @param k 目标和
* @return 和为k的子数组个数
*/
public int subarraySum(int[] nums, int k) {
// 计数器,记录和为k的子数组个数
int count = 0;
// 前缀和,记录从数组开始到当前位置的和
int pre = 0;
// 哈希表,记录前缀和出现的次数
HashMap < Integer, Integer > mp = new HashMap < > ();
// 初始化,前缀和为0的情况出现了1次
mp.put(0, 1);
// 遍历数组
for (int i = 0; i < nums.length; i++) {
// 更新前缀和
pre += nums[i];
// 检查是否存在前缀和为pre - k的情况
if (mp.containsKey(pre - k)) {
// 如果存在,累加对应的次数到结果
count += mp.get(pre - k);
}
// 更新哈希表,记录当前前缀和的出现次数
mp.put(pre, mp.getOrDefault(pre, 0) + 1);
}
return count;
}
}结构化讲解
面试时怎么讲
开场思路
这题我会用前缀和加哈希表,因为数组可能有负数,不能直接用滑动窗口。
核心过程
- 遍历数组时维护当前前缀和
sum。 - 如果历史上出现过前缀和
sum-k,这些位置到当前构成的子数组和就是k。 - 把对应出现次数累计到答案里。
- 最后再把当前前缀和写入哈希表,供后续位置查询。
复杂度总结
时间复杂度 O(n),空间复杂度 O(n)。
面试补一句:这题的关键句式是“子数组和 = 两个前缀和的差”。
核心思路
和为 K 的子数组不是滑动窗口题,因为数组可能有负数。更稳的做法是把区间和转成前缀和差值,再用哈希表统计历史前缀和出现次数。
步骤讲解
1
一边遍历一边累加前缀和
遍历到当前位置时,维护从起点到当前位置的前缀和 sum。
为什么这样做:任意子数组和都能写成两个前缀和的差。
对应代码提示:sum += num;
2
查询历史上有多少个 `sum-k`
如果之前出现过前缀和 sum - k,那么这些位置到当前位置形成的子数组和都等于 k。
为什么这样做:因为
sum - prev = k,等价于 prev = sum - k。对应代码提示:answer += count.getOrDefault(sum - k, 0);
3
把当前前缀和计入哈希表
处理完当前位置后,把当前前缀和出现次数加一,供后续位置使用。
为什么这样做:后面的子数组可能会把当前位置当成左边界之前的前缀。
对应代码提示:count.put(sum, count.getOrDefault(sum, 0) + 1);
易错点
先记录当前前缀和再查询
这样会把当前前缀和错误地和自己配对,导致多算。
正确理解:固定顺序:先查询
sum-k,再记录当前 sum。忘记初始化前缀和 0 的次数
这会漏掉从数组开头开始、刚好和为 k 的子数组。
正确理解:遍历前先放入
count.put(0, 1)。误用滑动窗口
数组里有负数时,窗口和不具备单调性,滑动窗口无法稳定收缩。
正确理解:优先转成前缀和差值问题处理。
复杂度与适用判断
时间复杂度:O(n)
空间复杂度:O(n)
比其他方案更好在哪里:比枚举所有子数组的
O(n^2) 暴力法高效很多,也规避了负数对滑动窗口的破坏。适用判断:题目要求统计某个区间和条件,且数组可能含负数时,优先考虑前缀和 + 哈希表。
额外提醒
- 初始化
sum = 0出现一次,是这题最容易漏掉的细节。
动画演示
如果你还没完全看懂,可以展开动画演示。
前缀和动画演示
想看这段解法是怎么一步步运行的,可以展开动画继续观察。
前缀和动画演示
想看这段解法是怎么一步步运行的,可以展开动画继续观察。
准备就绪 - 输入数组和k值,然后点击开始
找到的子数组
暂无结果,点击开始按钮查看算法执行过程...
动画演示仅在桌面端提供,移动端请优先阅读推荐代码与结构化讲解。