背景
题目链接:https://leetcode.com/problems/subarray-sum-equals-k/
要求就是:找出 sum = k 的子数组的个数。
在看这道题之前,先看两道简单的:
https://leetcode.com/problems/two-sum/
https://leetcode.com/problems/running-sum-of-1d-array/
two-sum
刷LeetCode的一定知道这个题目。
它的一个经典解法是用hashMap,代码如下:
func twoSum(nums []int, target int) []int {
// key: num[i], value: index
mp := make(map[int]int)
for k, v := range nums {
value, ok := mp[target - v]
if ok {
return []int{value, k}
}
mp[v] = k
}
return []int{}
}
running-sum-of-1d-array
这个题目很简单,running-sum 其实就是前缀和数组[prefixSum Array]。
func runningSum(nums []int) []int {
lth := len(nums)
res := make([]int, lth)
res[0] = nums[0]
for i := 1; i < lth; i++ {
res[i] = res[i-1] + nums[i]
}
return res
}
解题思路
sum = k 的子数组,可以表示为:
sum[i, j] = k
由于 sum[i, j] = sum[0, j] - sum[0, i - 1]
问题演化为:
sum[0, j] - sum[0, i - 1] = k
这里的sum[0, j] 、sum[0, i - 1]分别对应一个前缀和(prefixSum)。
问题进一步演化为:
prefixSum[j] - prefixSum[i - 1] = k
此时,这个问题就和two-sum很像了。
可以说,它就是two-subtraction。
最终代码如下:
func subarraySum(nums []int, k int) int {
prefixSum := runningSum(nums)
// key: prefixSum[i], value: frequency
mp := make(map[int]int)
mp[0] = 1
var res int
for i := 0; i < len(prefixSum); i++ {
v, ok := mp[prefixSum[i] - k]
if ok {
res += v
}
mp[prefixSum[i]] += 1
}
return res
}
参考资料
https://leetcode.com/problems/subarray-sum-equals-k/discuss/102106/Java-Solution-PreSum-%2B-HashMap