题目描述
给你一个整数数组
nums
和一个整数k
,请你统计并返回 该数组中和为k
的子数组的个数 。子数组是数组中元素的连续非空序列。
示例 1:输入:nums = [1,1,1], k = 2 输出:2
示例 2:输入:nums = [1,2,3], k = 3 输出:2
提示:
1 <= nums.length <= 2 *
-1000 <= nums[i] <= 1000
-
<= k <=
解题思路
要解决这个问题,我们可以使用前缀和(Prefix Sum)以及哈希表来优化查找和为 k
的子数组的个数。前缀和的基本思想是通过累积数组元素的和,可以快速计算出任意子数组的和。
具体步骤如下:
-
前缀和的定义:我们定义
目标是找到一个下标对prefixSum[i]
为数组nums
从第一个元素到第i
个元素的累积和。即prefixSum[i] = nums[0] + nums[1] + ... + nums[i]
。(i, j)
,使得prefixSum[j] - prefixSum[i-1] = k
,这里的i-1
是prefixSum
中i
的前一个位置。转换为查找问题就是:prefixSum[j] - k = prefixSum[i-1]
。 -
使用哈希表记录前缀和的出现次数:
我们用一个哈希表prefixSumCount
来记录每个前缀和出现的次数,键为前缀和,值为该前缀和的出现次数;在遍历数组的过程中,计算当前的前缀和currentSum
,然后检查哈希表中是否存在currentSum - k
。如果存在,则说明在此之前有一个子数组的和为k
,将结果计数加上对应的次数。 -
初始化和遍历:
初始化currentSum
为 0,同时在哈希表中加入prefixSumCount[0] = 1
,表示在开始前有一个空子数组的和为 0;遍历数组,更新currentSum
,并检查currentSum - k
是否在哈希表中,更新结果计数。最后,更新哈希表prefixSumCount
中currentSum
的次数。
复杂度分析
-
时间复杂度:O(n)。其中
n
是数组nums
的长度。我们只遍历一次数组,每次操作的时间复杂度是 O(1),因此总的时间复杂度是 O(n)。 -
空间复杂度:O(n)。在最坏的情况下,哈希表
prefixSumCount
需要存储n
个不同的前缀和,因此空间复杂度是 O(n)。
代码实现
package org.zyf.javabasic.letcode.hot100.substring;
import java.util.HashMap;
import java.util.Map;
/**
* @program: zyfboot-javabasic
* @description: 和为 K 的子数组
* @author: zhangyanfeng
* @create: 2024-08-21 21:36
**/
public class SubarraySumSolution {
public int subarraySum(int[] nums, int k) {
// 创建一个哈希表记录前缀和出现的次数
Map<Integer, Integer> prefixSumCount = new HashMap<>();
// 初始化前缀和为0的情况
prefixSumCount.put(0, 1);
int currentSum = 0; // 当前前缀和
int count = 0; // 和为k的子数组的数量
// 遍历数组
for (int num : nums) {
// 计算当前前缀和
currentSum += num;
// 检查是否存在一个前缀和,使得currentSum - k存在于哈希表中
if (prefixSumCount.containsKey(currentSum - k)) {
count += prefixSumCount.get(currentSum - k);
}
// 更新哈希表中当前前缀和的出现次数
prefixSumCount.put(currentSum, prefixSumCount.getOrDefault(currentSum, 0) + 1);
}
return count; // 返回和为k的子数组的个数
}
public static void main(String[] args) {
SubarraySumSolution solution = new SubarraySumSolution();
// 测试用例 1
int[] nums1 = {1, 1, 1};
int k1 = 2;
System.out.println(solution.subarraySum(nums1, k1)); // 输出: 2
// 测试用例 2
int[] nums2 = {1, 2, 3};
int k2 = 3;
System.out.println(solution.subarraySum(nums2, k2)); // 输出: 2
}
}
具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712