开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的33天,点击查看活动详情
题目:LeetCode
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 *该数组中和为 k ***的连续子数组的个数 。
示例 1:
输入: nums = [1,1,1], k = 2
输出: 2
示例 2:
输入: nums = [1,2,3], k = 3
输出: 2
提示:
-1000 <= nums[i] <= 1000
解题思路
解法一:
利用前缀和来求解,首先构建一个前缀和数组presum,数组长度为n+1,即前面多一个值为0的头,由前缀和公式可得 nums[i,j] = presum[j+1]-presum[i] 由此两次循环便可遍历所有子集合的和
解法二:
可以利用一个哈希表来存储前缀和数组pre,只需要判断当前前缀和减去目标和的值,即正好从该位置数第前k个数,pre[j] = pre[i] - k,即num[i]到num[j]之前数的和为k。为防止出现数组一k开头的情况,首先向map中加入(0,1)的数据
代码实现
解法一:
public int subarraySum(int[] nums, int k) {
// 前缀和数组
int[] presum = new int[nums.length + 1];
for (int i = 0; i < nums.length; i++) {
presum[i+1] = nums[i] + presum[i];
}
// 统计个数
int count = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
//注意偏移,因为我们的nums[2]到nums[4]等于presum[5]-presum[2]
//所以这样就可以得到nums[i,j]区间内的和
if (presum[j+1] - presum[i] == k){
count++;
}
}
}
return count;
}
解法二:
public int subarraySum(int[] nums, int k) {
int pre = 0,res = 0;
Map<Integer, Integer> map = new HashMap<>();
// 解决k = num[i]情况
map.put(0,1);
for (int i = 0; i < nums.length; i++) {
pre += nums[i];
if (map.containsKey(pre - k)){
res += map.get(pre-k);
}
map.put(pre,map.getOrDefault(pre,0)+1);
}
return res;
}
运行结果
复杂度分析
解法一:
- 空间复杂度:
- 时间复杂度:
解法二:
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN) 一起分享知识, Keep Learning!