给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
枚举左右边界,计算区间内的和满足k的区间个数。
复杂度分析:
时间复杂度:O(n^2),其中 n 为数组的长度。枚举子数组开头和结尾需要 O(n^2)的时间,其中求和需要 O(1) 的时间复杂度,因此总时间复杂度为 O(n^2)。
空间复杂度:O(1)。只需要常数空间存放若干变量。
定义数组 sum[j] 为[0…j]所有元素的和,那么sum[j]可以由sum[j-1]递推而来,sum[j]=sum[j-1]+nums[j],则[i…j]这个子数组的和可以表示为 s[i…j]=sum[j]-sum[i-1],要使这个子数组的和为k,也就是s[i…j]=sum[j]-sum[i-1]=k,即sum[i-1]=sum[j]-k。当获得sum[j]的值的时候,先去检查曾经是否有sum[j]-k也就是sum[i-1]出现过。如果出现过,就说明存在子数组s[i…j]之和为k的情况。
这可以借助哈希表保存累加和sum及出现的次数。若累加和sum−k在哈希表中存在,则说明存在连续子数组之和为k。由于 sum[i] 的计算只与前一项的答案有关,因此我们可以不用建立 sum 数组,直接用 sum 变量来记录 sum[i−1] 的答案即可。
具体做法是:
1)初始化哈希表hash={0:1},表示累加和为0,出现了1次。初始化累加和sum=0。初始化结果res=0。
2)遍历数组:
2.1)更新累加和sum+=nums[i];
2.2)若sum-k存在于hash中,说明存在连续子数组之和为k。则令res+=hash[sum-k],表示sum-k出现几次,就存在几种子数组之和为k。
2.3)若sum存在于hash中,将其出现次数加一。若不存在,将其加入hash。
3)返回res。
复杂度分析:
时间复杂度:O(n),其中 n 为数组的长度。我们遍历数组的时间复杂度为 O(n),中间利用哈希表查询删除的复杂度均为 O(1),因此总时间复杂度为 O(n)。
空间复杂度:O(n),其中 n 为数组的长度。哈希表在最坏情况下可能有 n 个不同的键值,因此需要 O(n) 的空间复杂度。
Python代码如下:
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
res = 0
for i in range(len(nums)):
s = 0
for j in range(i, len(nums)):
s += nums[j]
if s == k:
res += 1
return res
Java代码如下:
class Solution {
public int subarraySum(int[] nums, int k) {
int n = nums.length;
int res = 0;
for(int i=0; i<n; i++){
int s = 0;
for(int j=i; j<n; j++){
s += nums[j];
if(s==k){
res++;
}
}
}
return res;
}
}
Python代码如下:
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
hash_dic = {0:1}
res = 0
s = 0
for i in range(len(nums)):
s += nums[i]
if s-k in hash_dic:
res += hash_dic[s-k]
if s in hash_dic:
hash_dic[s] += 1
else:
hash_dic[s] = 1
return res
Java代码如下:
class Solution {
public int subarraySum(int[] nums, int k) {
HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>();
hash.put(0, 1);
int sum = 0;
int res = 0;
for(int i=0; i<nums.length; i++){
sum += nums[i];
if(hash.containsKey(sum-k)){
res += hash.get(sum-k);
}
// // 写法一
// if(hash.containsKey(sum)){
// hash.put(sum, hash.get(sum)+1);
// }else{
// hash.put(sum, 1);
// }
// 写法二
hash.put(sum, hash.getOrDefault(sum, 0) + 1);
}
return res;
}
}