📜  总和等于其长度的子数组的计数|套装2(1)

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

总和等于其长度的子数组的计数

问题描述

给定一个整数数组 nums,请你计算并返回满足以下条件的非空连续子数组的数量:该子数组的长度、元素和均为 k

示例
示例一
输入: nums = [1,1,1], k = 2
输出: 2
解释: 
子数组 [1,1] 和 [1,1] 满足长度和元素和都为 2,因此满足条件的子数组总共有 2 个。
示例二
输入: nums = [1,2,3], k = 3
输出: 2
解释: 
子数组 [2,1] 和 [3] 满足长度和元素和都为 3,因此满足条件的子数组总共有 2 个。
解法

我们可以使用一个前缀和数组 preSum,其中 sum[i] 表示从数组的第一个元素到第 $i$ 个元素的和。

对于 preSum 数组中的每个元素 preSum[i],我们需要找到满足以下条件的 preSum[j]

$$ preSum[j] - preSum[i-1] = k $$

上式表达的意思是:$i$ 和 $j$ 之间的连续子数组的和为 $k$。因此我们可以使用一个哈希表 countMap,其中:

  • 键是 preSum[i] - k,表示满足 $preSum[j] - preSum[i-1] = k$ 的 $preSum[i-1]$ 的数量。
  • 值是前缀和的数量,即在位置 i 之前,有多少个前缀和等于 preSum[i] - k

然后我们遍历数组,在遍历到位置 i 时,我们计算 preSum[i],并查找哈希表中是否有键为 preSum[i] - k 的项,如果有,则将对应项的值累加到结果中。

最后我们将 preSum[i] 添加到哈希表中,以便我们可以找到和它相等的前缀和。

代码实现
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        countMap = {0: 1}
        preSum = 0
        count = 0

        for num in nums:
            preSum += num
            if preSum - k in countMap:
                count += countMap[preSum - k]
            if preSum in countMap:
                countMap[preSum] += 1
            else:
                countMap[preSum] = 1

        return count
时间复杂度
  • 遍历一遍数组,时间复杂度 $O(n)$。
  • 在哈希表中查找一个键的时间复杂度是 $O(1)$,因此最坏时间复杂度为 $O(n)$。

因此总时间复杂度为 $O(n)$。

空间复杂度

哈希表最多需要存储 $n+1$ 个元素,因此空间复杂度为 $O(n)$。