📌  相关文章
📜  总和至少为 K 的子数组计数(1)

📅  最后修改于: 2023-12-03 14:54:20.777000             🧑  作者: Mango

总和至少为 K 的子数组计数

什么是子数组?

子数组是指一个数组中连续的一段元素构成的数组,比如:

[1, 2, 3, 4]
[1, 2]
[3, 4]
[2, 3, 4]

都是数组 [1, 2, 3, 4] 的子数组。

问题描述

给定一个整数数组 nums 和一个整数 K ,你需要找到该数组中和至少为 K 的连续子数组的个数。

示例:

输入: nums = [1,2,3,4], k = 7
输出: 0
解释: 该数组中不存在和至少为 7 的连续子数组。
输入: nums = [3,2,3,1,2,4,5,5,6], k = 7
输出: 6
解释: [3,2,3], [2,3,1,2], [3,1,2,4], [1,2,4,5], [2,4,5], [5,5,6] 是和至少为 7 的连续子数组。
解题思路

我们可以用前缀和来解决这个问题。对于一个区间 $[i,j]$ ,若前缀和 $sum_j \geqslant sum_i + K$ ,则说明从 $i$ 到 $j$ 存在一个子数组和至少为 $K$。

因此我们可以用一个变量 count 记录子数组的数量,每次遍历到下一个元素时,我们就遍历该元素前面的所有前缀和,看看有几个前缀和满足上面的条件。

具体实现见下方代码片段。

参考代码
def subarray_sum(nums, k):
    count = 0
    pre_sum = 0
    prefix_sum = {0: 1}  # 存储前缀和及其出现次数
    for i in range(len(nums)):
        pre_sum += nums[i]
        if pre_sum - k in prefix_sum:
            count += prefix_sum[pre_sum - k]
        prefix_sum[pre_sum] = prefix_sum.get(pre_sum, 0) + 1
    return count

代码解释:

  • count 记录子数组的数量;
  • pre_sum 记录当前的前缀和;
  • prefix_sum 用字典存储前缀和及其出现次数;
  • 遍历数组 nums ,每次更新前缀和 pre_sum
  • 如果 pre_sum - k 在字典中出现过,则说明从上一次出现的位置到当前位置的子数组和至少为 k,更新 count
  • 更新字典 prefix_sum