Medium
题目描述
给你一个整数数组 nums 和一个整数 k ,请你统计并返回该数组中和为 k 的连续子数组的个数。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
1 <= nums.length <= 2 * 10^4-1000 <= nums[i] <= 1000-10^7 <= k <= 10^7
解题思路
解题思路
方法一:暴力解法 枚举所有可能的子数组,计算每个子数组的和,统计和为 k 的子数组个数。时间复杂度为 O(n²)。
方法二:前缀和 + 哈希表(推荐) 这是最优解法,核心思想是利用前缀和的性质。
对于任意两个位置 i 和 j(i < j),如果从位置 i+1 到位置 j 的子数组和为 k,那么有:
prefixSum[j] - prefixSum[i] = k,即 prefixSum[i] = prefixSum[j] - k
算法步骤:
- 使用哈希表存储前缀和出现的次数
- 遍历数组,计算当前位置的前缀和
- 查找哈希表中是否存在
prefixSum - k,如果存在,说明找到了和为 k 的子数组 - 将当前前缀和加入哈希表
关键点是初始化哈希表时要加入 {0: 1},表示前缀和为 0 出现了 1 次,这样可以处理从数组开头开始的子数组。
时间复杂度 O(n),空间复杂度 O(n),是最优解法。
代码实现
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> prefixSumCount;
prefixSumCount[0] = 1;
int prefixSum = 0;
int count = 0;
for (int num : nums) {
prefixSum += num;
if (prefixSumCount.find(prefixSum - k) != prefixSumCount.end()) {
count += prefixSumCount[prefixSum - k];
}
prefixSumCount[prefixSum]++;
}
return count;
}
};
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
prefix_sum_count = {0: 1}
prefix_sum = 0
count = 0
for num in nums:
prefix_sum += num
if prefix_sum - k in prefix_sum_count:
count += prefix_sum_count[prefix_sum - k]
prefix_sum_count[prefix_sum] = prefix_sum_count.get(prefix_sum, 0) + 1
return count
public class Solution {
public int SubarraySum(int[] nums, int k) {
Dictionary<int, int> prefixSumCount = new Dictionary<int, int>();
prefixSumCount[0] = 1;
int prefixSum = 0;
int count = 0;
foreach (int num in nums) {
prefixSum += num;
if (prefixSumCount.ContainsKey(prefixSum - k)) {
count += prefixSumCount[prefixSum - k];
}
if (prefixSumCount.ContainsKey(prefixSum)) {
prefixSumCount[prefixSum]++;
} else {
prefixSumCount[prefixSum] = 1;
}
}
return count;
}
}
var subarraySum = function(nums, k) {
const prefixSumCount = new Map();
prefixSumCount.set(0, 1);
let prefixSum = 0;
let count = 0;
for (const num of nums) {
prefixSum += num;
if (prefixSumCount.has(prefixSum - k)) {
count += prefixSumCount.get(prefixSum - k);
}
prefixSumCount.set(prefixSum, (prefixSumCount.get(prefixSum) || 0) + 1);
}
return count;
};
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 前缀和 + 哈希表 | O(n) | O(n) |
| 暴力解法 | O(n²) | O(1) |
相关题目
. Two Sum (Easy)
. Continuous Subarray Sum (Medium)
. Subarray Product Less Than K (Medium)
. Find Pivot Index (Easy)
. Subarray Sums Divisible by K (Medium)
. K Radius Subarray Averages (Medium)
. Maximum Sum Score of Array (Medium)