📌  相关文章
📜  国际空间研究组织 | ISRO CS 2011 |问题 54(1)

📅  最后修改于: 2023-12-03 15:07:33.797000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2011 |问题 54

题目描述

给定一个长度为 $n$ 的数组 $a$,请你计算包含 $a$ 中相邻元素之和的数量,使得该数量不超过给定的整数 $k$。

函数签名
def subarraySum(a: List[int], k: int) -> int:
    pass
输入
  • $a$:一个长度为 $n$ 的整数数组 $(1≤n≤2×10^4,−10^4≤a_i≤10^4)$。
  • $k$:整数 $(−10^9≤k≤10^9)$。
输出
  • 返回一个整数,表示 $a$ 包含相邻元素之和不超过 $k$ 的数量。
例子
例子1
assert subarraySum([1, -1, 0], 0) == 3
例子2
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