10.和为 K 的子数组

目录

  • 问题链接:
  • 问题描述:
  • 实例:
  • 代码1:
  • 代码2:
  • 知识补充:
    • 前缀和:
    • 枚举右,维护左:

问题链接:

和为 K 的子数组

问题描述:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数
子数组是数组中元素的连续非空序列。

实例:

示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2

代码1:

前缀和加哈希:两次循环

  1. 前缀和数组:构建 s [ i + 1 ] = s [ i ] + n u m s [ i ] s[i+1] = s[i] + nums[i] s[i+1]=s[i]+nums[i] s [ 0 ] = 0 s[0]=0 s[0]=0记录前i项和
  2. 哈希计数:用cnt字典统计各前缀和出现次数
  3. 动态统计:遍历时计算 s [ j ] − k s[j]-k s[j]k在历史前缀和中的出现次数,累加到结果
  4. 实时更新:将当前前缀和存入字典,供后续元素查询使用
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        s=[0]*(len(nums)+1)
        for i,x in enumerate(nums):
            s[i+1]=s[i]+x   #计算前缀和
        ans=0
        cnt=defaultdict(int)  #存放
        for sj in s:   #枚举右边的j
            ans+=cnt[sj-k]   #s[j]-k=s[i]:统计有多少个s[i]满足
            cnt[sj]+=1
        return ans

代码2:

前缀和加哈希:一次循环

  1. 初始化:cnt哈希表预存{0:1},处理前缀和直接等于k的情况(如首元素即满足)。
  2. 遍历计算前缀和: s = ∑ i = 0 n n u m s [ i ] s = \sum_{i=0}^{n} nums[i] s=i=0nnums[i],每个新元素更新当前前缀和s。
  3. 动态统计结果:利用cnt[s-k]查找能与当前前缀和形成差值为k的历史记录数量,累加到结果ans。
  4. 更新哈希表:将当前前缀和s存入哈希表,为后续计算提供数据支持。
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        ans = s = 0
        cnt = defaultdict(int)
        cnt[0] = 1  # s[0]=0 单独统计
        for x in nums:
            s += x
            ans += cnt[s - k]
            cnt[s] += 1
        return ans

知识补充:

前缀和:

定义:

s[0]=0, s[i+1]=nums[0]+nums[1]++nums[i]

设 i

枚举右,维护左:

1.把 s[j]−s[i]=k 移项,得s[i]=s[j]−k
2.遍历 s,一边枚举右边的 j,一边统计左边有多少个 s[i] 满足 i

例:
以 nums=[1,1,−1,1,−1], k=1 为例,其前缀和 s=[0,1,2,1,2,1]。
比如 s[j]=2,那么 s[i]=s[j]−k=2−1=1,我们要找的是前面遍历过的前缀和中有多少个 1。

j s[j] s[j]-k s[j]-k的个数(s[i]的个数) 解释
0 0 -1 0
1 1 1 1 s[0]=0
2 2 1 1 s[1]=1
3 1 1 1 s[0]=0
4 2 2 2 s[1]=s[3]=1
5 1 1 1 s[0]=0

总计有 0+1+1+1+2+1=6 个和为 k=1 的子数组。

你可能感兴趣的:(Leetcode热门算法题,leetcode,算法,python)