📌 和为 K 的子数组 ------ 知识点总结
🧩 题目描述
给定一个整数数组,统计其中连续子数组 的和等于 K 的个数。
🔍 示例理解
示例1
数组:[1, 2, 3],K = 3
符合条件的子数组:
[1, 2] = 3[3] = 3
👉 答案:2
示例2(含负数)
数组:[1, -1, 2, 3, -2, 4],K = 3
符合条件的子数组有多个(包含跨区间组合)
👉 说明:负数存在时,不能用滑动窗口
❌ 暴力解法
思路
- 枚举所有起点
- 枚举所有终点
- 计算区间和是否等于 K
复杂度
- 时间复杂度:
O(n²) - 空间复杂度:
O(1)
缺点
- 逐个累加太慢
- 无法处理大规模数据
🚀 最优解:前缀和 + 哈希表
💡 核心思想
定义前缀和:
prefix[i] = 从数组起点到 i 的累加和
关键公式:
区间和 = prefix[j] - prefix[i]
如果:
prefix[j] - prefix[i] = K
→ prefix[i] = prefix[j] - K
👉 转化为:
在当前前缀和 sum 之前,有多少个 sum - K
🧠 算法思路
使用哈希表记录:
前缀和出现的次数
遍历数组时:
- 更新当前前缀和
sum - 查询
sum - K是否出现过- 出现次数 = 以当前结尾的合法区间数量
- 将当前
sum加入哈希表
🧾 初始化细节
必须初始化:
hashmap[0] = 1
原因:
- 表示"从起点开始的区间"
⚙️ 算法步骤
-
初始化:
sum = 0count = 0hashmap = {0: 1}
-
遍历数组:
- 累加前缀和
sum += nums[i] - 查找
sum - K- 若存在,
count += hashmap[sum - K]
- 若存在,
- 更新
hashmap[sum] += 1
- 累加前缀和
-
返回
count
⏱️ 复杂度分析
- 时间复杂度:
O(n) - 空间复杂度:
O(n)(哈希表)
🎯 核心总结
- 子数组问题 → 优先考虑 前缀和
- "区间和问题" → 转化为 "两个前缀和之差"
- 用哈希表优化查找过程
- 遇到负数 → 滑动窗口失效,必须用前缀和
🧠 一句话记忆
"当前前缀和 - K,如果以前出现过,就说明存在满足条件的子数组。"
cpp
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count = 0;
map<int, int> m;
m[0] = 1;
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
if (m.find(sum - k) != m.end()) {
count += m[sum - k];
}
m[sum]++;
}
cout << "count: " << count << endl;
return count;
}
};