题目描述
思路
前缀和 + HashMap, 时间复杂度O(N), 空间复杂度O(N)
暴力枚举,时间复杂度O(N^2),空间复杂度O(1)
枚举所有子数组
代码
前缀和+hashmap
- 如何利用前缀和?数组中两个元素的前缀和之差可以转化为子数组的各个元素之和
- 可以O(N^2)内外层遍历数组,用前缀和之差来找出所有“红色子数组和”,同时与target比较计数。时间复杂度仍为O(n^2),空间复杂度成了 O(n)
- 使用前缀和后,再利用hashmap,map里存放<本数组可能出现的前缀和,该前缀和出现的次数>。遍历一次数组,看
preSum[i] - k
是否在map中,如果在map中,计数就加上这个前缀和preSum[i] - k
出现的次数。-
注意:别漏掉从
preSum[0]
到preSum[n]
构成的前缀和,需要先在map中添加(0,1)
-
class Solution {
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();//使用map记录出现同样的和的次数
map.put(0, 1);//这里需要预存前缀和为 0 的情况,会漏掉前几位就满足的情况
int count = 0;
int preSum = 0;
for (int i = 0; i < nums.length; i++) {
preSum = preSum + nums[i];//计算当前位上的前缀和
if (map.containsKey(preSum - k)) {
count = count + map.get(preSum - k);
}
map.put(preSum, map.getOrDefault(preSum, 0) + 1);//记录当前前缀和出现的次数
}
return count;
}
}
暴力
//暴力法 O(N^2)
class Solution {
public int subarraySum(int[] nums, int k) {
int l = nums.length;
int count = 0;
for (int i = 0; i < l; i++) {
int sum = 0;
for (int j = i; j < l; j++) {
sum += nums[j];
if (sum == k) {
count++;
}
}
}
return count;
}
}