10.和为K的子数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
- 1 <= nums.length <= 2 * 104
- -1000 <= nums[i] <= 1000
- -107 <= k <= 107
思路:
由于子数组表示的数组中元素的连续非空序列,所以题目意思就是让我们找一个区间使得区间和为k,由此我们可以联想到前缀和,pre[i]表示数组前i个元素的和,则pre[j]-pre[i]即为第i+1个元素到第j个元素的和,即区间[i+1,j]的元素和,容易想到可以遍历左右端点来确定区间,利用前缀和判断区间和是否满足条件,时间复杂度为n2
class Solution {
public int subarraySum(int[] nums, int k) {
int res = 0;
int len = nums.length;
int[] temp = new int[100005];
for(int i = 1;i<=len;i++){
temp[i] = temp[i-1]+nums[i-1];
}
for(int i = 1;i <= len;i++){
for(int j = i;j <= len;j++){
if(temp[j]-temp[i-1]==k)res++;
}
}
return res;
}
}
考虑优化:
假设区间[i+1,j]的数组和等于k,即pre[j]-pre[i]==k,那是不是说明pre[i]=pre[j]-k,由于i比j小,故pre[i]肯定比pre[j]先计算,我们只需要遍历一个变量j,并判断pre[j]-k是否已经存在,存在的次数即为满足条件的区间个数,遍历过程中需要不断记录pre[j]出现次数,即将pre[j]记录在hashMap中
class Solution {
public int subarraySum(int[] nums, int k) {
int res = 0,pre = 0;
Map<Integer,Integer>mp = new HashMap<>();
mp.put(0, 1);
for(int i = 0;i < nums.length;i++){
pre += nums[i];
if(mp.containsKey(pre-k))res+=mp.get(pre-k);
mp.put(pre,mp.getOrDefault(pre,0)+1);
}
return res;
}
}

浙公网安备 33010602011771号