636 字
3 分钟
和为 K 的子数组

题目描述
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
解题思路
- 前缀和转换:
- 将子数组和问题转化为前缀和之差问题
- 哈希表优化:
- 使用哈希表记录各前缀和出现次数
- 实时计算:
- 遍历时计算当前前缀和
curr_sum
- 遍历时计算当前前缀和
- 差值匹配:
- 查找
curr_sum - k
是否在历史前缀和中
- 查找
- 计数更新:
- 匹配成功则累加对应出现次数
- 更新存储:
- 将当前前缀和加入哈希表
关键洞察
- 前缀和性质:
sum[i..j] = prefix[j] - prefix[i-1]
- 两数差转化:
prefix[j] - prefix[i] = k
等价于prefix[i] = prefix[j] - k
- 哈希表高效查询:
- O(1) 时间查询历史前缀和
- 初始化技巧:
- 预先存入
{0:1}
处理从头开始的子数组
- 预先存入
- 顺序处理:
- 单次遍历完成计数,避免嵌套循环
- 负数和处理:
- 天然支持含负数的数组
复杂度分析
指标 | 说明 |
---|---|
时间复杂度 | O(n):单次遍历数组 |
空间复杂度 | O(n):哈希表存储前缀和 |
最优情况 | O(n):所有元素相同时 |
最坏情况 | O(n):前缀和均不同时 |
代码实现
/** * @param {number[]} nums * @param {number} k * @return {number} */var subarraySum = function (nums, k) { let result = 0, sum = 0; const map = { 0: 1 }; for (const num of nums) { sum += num; if (map[sum - k]) { result += map[sum - k]; } map[sum] = (map[sum] || 0) + 1 } return result;};
use std::collections::HashMap;
impl Solution { pub fn subarray_sum(nums: Vec<i32>, k: i32) -> i32 { let mut sum = 0; let mut result = 0; let mut map = HashMap::new(); map.insert(0, 1); for num in nums { sum = sum+num; if let Some(&count) = map.get(&(sum-k)) { result+=count; } *map.entry(sum).or_insert(0)+=1; } return result; }
from collections import defaultdict
class Solution: def subarraySum(self, nums: List[int], k: int) -> int: map = defaultdict(int) map[0] = 1 count = 0 sum = 0
for num in nums: sum+=num if sum - k in map: count += map[sum-k] map[sum]+=1
return count
实际应用场景
- 金融分析:寻找特定收益率的交易区间`
- 基因序列:DNA序列中特定碱基和片段定位`
- 流量监控:网络流量中特定数据包序列检测`
- 库存管理:库存变化满足特定总量的时段`