在一维的时候,也即给出一个整数序列a1,a2,a3...an我们需要求解出区间总和等于t的区间数目,对于当前的右端点i,我们需要找到左端点j使得s[i] - s[j - 1] = t,也即对于右端点i,s[j - 1] = s[i] - t,我们可以可以使用前缀和 + 哈希表解决的,前缀和计算出所有区间[0, n]的区间总和,我们可以在遍历的时候求解出以当前i为区间右端点,判断哈希表中是否存在s[i] - t的值,如果存在说明存在[j, i]区间使得区间和等于t的,并且在遍历的时候使用哈希表来记录前缀和出现的次数,这样在下一次的时候才可以直接从哈希表中直接判断是否可以找到以当前的i为右端点左边的端点j使得区间和等于t,我们可以画出下面的图:
代码如下:
from typing import List
import collections
# 在nums的所有区间中求解有多少个区间总和等于t的数目, t为目标值
def cal(nums: List[int], t: int):
n = len(nums)
s = [0] * (n + 1)
for i in range(1, n + 1):
s[i] = s[i - 1] + nums[i - 1]
dic = collections.defaultdict(int)
dic[0] = 1
res = 0
# 边遍历的时候将值存储到哈希表中
for i in range(1, n + 1):
if dic[s[i] - t] > 0:
res += dic[s[i] - t]
# 记录区间前缀和
dic[s[i]] += 1
return res
if __name__ == '__main__':
nums = [3, 2, -1, 2, 7, 5, -1, -1, 3, 1, 2]
print(cal(nums, 3))
优化版本:在遍历的时候维护前缀和即可,这样可以少遍历一次nums数组
from typing import List
import collections
def cal(nums: List[int], t: int):
n = len(nums)
s = 0
dic = collections.defaultdict(int)
dic[0] = 1
res = 0
# 边遍历的时候边计算前缀和即可
for i in range(1, n + 1):
s += nums[i - 1]
if dic[s - t] > 0:
res += dic[s - t]
dic[s] += 1
return res
if __name__ == '__main__':
nums = [3, 2, -1, 2, 7, 5, -1, -1, 3, 1, 2]
print(cal(nums, 3))