🔍 LeetCode 560. 和为 K 的子数组 题解
📌 题目难度 :中等
📌 标签:数组、哈希表、前缀和
1. 问题理解
给定一个整数数组 nums 和一个整数 k,需要返回 连续子数组 中和为 k 的个数。
示例
输入: nums = [1,1,1], k = 2
输出: 2
解释: [1,1] 出现两次(索引 0~1 和 1~2)
2. 从暴力解法出发
2.1 最直观的思路
我们可以枚举所有可能的连续子数组,计算它们的和,统计等于 k 的个数。
java
int count = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
int sum = 0;
for (int m = i; m <= j; m++) {
sum += nums[m];
}
if (sum == k) count++;
}
}
时间复杂度:O(n³),不可接受。
3. 第一次优化:前缀和
3.1 什么是前缀和?
我们定义一个数组 pre,其中 pre[i] 表示从 nums[0] 到 nums[i-1] 的和。
比如:
nums = [1, 2, 3]
pre = [0, 1, 3, 6]
那么子数组 nums[i..j] 的和 = pre[j+1] - pre[i]。
3.2 优化后的暴力枚举
java
int[] pre = new int[nums.length + 1];
for (int i = 0; i < nums.length; i++) {
pre[i + 1] = pre[i] + nums[i];
}
int count = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
if (pre[j + 1] - pre[i] == k) {
count++;
}
}
}
时间复杂度:O(n²),依然可能超时。
4. 最终优化:前缀和 + 哈希表
4.1 思路转变
我们不再枚举所有子数组,而是 在遍历过程中,快速判断是否存在符合条件的起点。
核心公式:
pre[j+1] - pre[i] == k
等价于
pre[i] == pre[j+1] - k
也就是说,当我们遍历到 j 时,我们想知道有多少个 i 满足 pre[i] == pre[j+1] - k。
4.2 用哈希表记录前缀和出现次数
我们可以在遍历数组的过程中:
- 维护当前的前缀和
currentSum - 检查
currentSum - k在之前出现过几次(即有多少个起点) - 每次将当前前缀和存入哈希表
4.3 代码实现
java
public int subarraySum(int[] nums, int k) {
// key: 前缀和, value: 出现次数
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1); // 初始状态:前缀和为0出现1次
int currentSum = 0;
int count = 0;
for (int num : nums) {
currentSum += num;
// 如果存在 currentSum - k,说明找到了以当前结尾的子数组
if (map.containsKey(currentSum - k)) {
count += map.get(currentSum - k);
}
// 将当前前缀和存入哈希表
map.put(currentSum, map.getOrDefault(currentSum, 0) + 1);
}
return count;
}
5. 为什么这样不会遗漏?
举个例子:
nums = [1, 2, -2, 1, -1], k = 1
前缀和变化过程:
0 → 1 → 3 → 1 → 2 → 1
遍历到最后一个 -1 时,当前和为 1,currentSum - k = 0,哈希表中 0 出现了一次,说明从开头到当前位置的和为 1,正好符合条件。
我们一边遍历一边更新哈希表,相当于 固定了子数组的结尾,用哈希表快速查找符合条件的开头。
6. 复杂度分析
- 时间复杂度:O(n),只需遍历一次数组
- 空间复杂度:O(n),哈希表存储前缀和
7. 总结
| 方法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 暴力枚举 | O(n³) | O(1) | 不可行 |
| 前缀和 + 双重循环 | O(n²) | O(n) | 可能超时 |
| 前缀和 + 哈希表 | O(n) | O(n) | ✅ 最优解 |
核心思想:用空间换时间,通过哈希表快速查找目标前缀和。
8. 写在最后
这道题是"前缀和"类题目的经典代表,也是面试中高频出现的题目之一。理解了这个思路,你就能轻松应对类似问题,比如:
如果这篇文章对你有帮助,欢迎点赞、收藏、转发~ 🚀