题目:LCR 010
解法一:枚举
直接遍历所有的两元素组合,一个元素作为开始元素,一个元素作为结尾元素,在遍历时直接累加sum,避免得到开始元素和结束元素后再重复计算子数组的和
class Solution {
public int subarraySum(int[] nums, int k) {
int sum = 0, res = 0;
for (int i = 0; i < nums.length; i++) {
sum = 0;
for (int j = i; j < nums.length; j++) {
sum += nums[j];
if (sum == k) res++;
}
}
return res;
}
}
注意:i
和j
都从0
开始遍历,就会对相同的子数组计算2次,分别是[i~j]
和[j~i]
,因此j
要从i
开始遍历
解法二:前缀和 + 哈希表优化
以索引j
结尾的前缀和sum(j)
,当存在以索引i
结尾(i<j)
的前缀和sum(i)
,满足子数组sum(j)-sum(i)=k
时,则以i
为起始元素,以j
为结尾元素的子数组,即为符合条件的数组
class Solution {
public int subarraySum(int[] nums, int k) {
int sum = 0, res = 0;
Map<Integer, Integer> map = new HashMap<>();
//必要,因为当符合条件的子数组从0位置开始时,sum = k,调用map.getOrDefault(sum - k, 0)时就会用到(0, 1)
map.put(0, 1);
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
res += map.getOrDefault(sum - k, 0);
//查找完符合条件的结果之后,再将当前循环的结果存入map
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return res;
}
}
注意:
- map需要存入(0, 1),因为当符合条件的子数组从0位置开始时,sum = k,调用map.getOrDefault(sum - k, 0)时就会用到(0, 1)
- 每次计算先查找结果,再将当前遍历的前缀和存入map