题目链接:
题目描述:
思路:
思路一
子数组有两个边界,可以先固定左边界,然后遍历右边界,一边遍历一边求和
用两个for循环
思路二
用前缀和,前缀和就是数组累计求和
如【1 1 1】,前缀和【1 2 3】
设
i
i
i处的前缀和为
p
r
e
(
i
)
pre(i)
pre(i),则:
p
r
e
(
i
)
=
p
r
e
(
i
−
1
)
+
n
u
m
s
[
i
]
pre(i) = pre(i-1) + nums[i]
pre(i)=pre(i−1)+nums[i]
如果求某个子数组【i,j】的和,
s
u
m
=
p
r
e
(
j
)
−
p
r
e
(
i
−
1
)
sum = pre(j) - pre(i-1)
sum=pre(j)−pre(i−1)
我们现在知道了
p
r
e
(
j
)
pre(j)
pre(j),所以只需要看有几个
p
r
e
(
i
−
1
)
=
p
r
e
(
j
)
−
s
u
m
pre(i-1)=pre(j)-sum
pre(i−1)=pre(j)−sum就行
如【1 1 1】,应该是【3-0】,所以要有一个初始的前缀和0
上面的公式类似于求两数之和,可以用map方便查找,
key是前缀和,value是前缀和的个数
实现代码:
class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0, n = nums.length;
//固定左
for(int l = 0; l < n; l++){
int sum = 0;
//遍历右
for(int r = l; r < n; r++){
sum += nums[r];
if(sum == k){
count++;
}
}
}
return count;
}
}
class Solution {
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
map.put(0,1);
int pre = 0,count = 0;
for(int i = 0; i<nums.length; i++){
pre += nums[i];
if(map.containsKey(pre-k)) {
count += map.get(pre-k);
}
map.put(pre,map.getOrDefault(pre,0)+1);
}
return count;
}
}