思路
前缀和
public static int subarraySum(int[] nums, int k) {
int ret = 0;
Map<Integer, Integer> map = new HashMap<Integer, Integer>(); // 注1
int sum = 0;
map.put(0, 1); // 注2
for (int i = 0; i < nums.length; i++)
{
sum += nums[i];
if (map.containsKey(sum - k)) // 因为j可以代表的和一定位于i之前,
ret += map.get(sum - k); // 所以这里很巧妙的保证了j一定位于i的前面
map.put(sum, map.getOrDefault(sum, 0) + 1); // sum的范围是[j+1, i] 注3
}
return ret;
}
【注1】这里map中的元素放置说明为<和, 可行的j
的位置个数>;
【注2】这里需要提前加入元素<0, 1>,表示j
为-1
时候,即不将j
放入子数组,此时和为0
,也是有可能的子数组序列;
【注3】这行代码不能调整到if
之前。
在当前的代码顺序下,j
的搜索范围为[-1, i-1]
,因此有效连续子数组的范围为[0, i]
,和[i, i]
。
如果将注1代码调整顺序到if
之前的话,j
的搜索范围为[-1, i]
,有效连续子数组的范围扩大到[i+1, i]
,显然是不合理的。