📅  最后修改于: 2023-12-03 15:07:33.797000             🧑  作者: Mango
给定一个长度为 $n$ 的数组 $a$,请你计算包含 $a$ 中相邻元素之和的数量,使得该数量不超过给定的整数 $k$。
def subarraySum(a: List[int], k: int) -> int:
pass
assert subarraySum([1, -1, 0], 0) == 3
assert subarraySum([1, 1, 1], 2) == 2
我们可以用一个前缀和 $s$ 来求出 $a$ 的所有子数组和,即 $s[i]=a[0]+a[1]+...+a[i]$。
我们可以用两个指针 $i$ 和 $j$ 来遍历所有的子数组,其中 $i$ 表示左端点,$j$ 表示右端点,显然对于一个 $i$,它对应的所有区间的左端点都是 $i$,因此我们需要枚举右端点,然后计算对应的区间和。
对于每个右端点 $j$,我们计算子数组 $i$ 到 $j$ 的和,即 $s[j]-s[i-1]$,然后判断该和是否不超过 $k$,如果不超过的话我们就更新答案。
最后返回答案即可。
from typing import List
def subarraySum(a: List[int], k: int) -> int:
s = [0] * (len(a) + 1)
for i in range(1, len(a) + 1):
s[i] = s[i - 1] + a[i - 1]
ans = 0
for i in range(1, len(s)):
for j in range(i, len(s)):
if s[j] - s[i - 1] <= k:
ans += 1
return ans
以上代码的时间复杂度为 $O(n^2)$,空间复杂度为 $O(n)$。
这个解法的优化是可以用哈希表来记录每个前缀和出现的次数,这样我们在判断 $s[j]-s[i-1]$ 是否小于等于 $k$ 的时候可以用 $O(1)$ 的时间复杂度来完成,从而将时间复杂度优化至 $O(n)$。详见 LeetCode 560. Subarray Sum Equals K。