剑指 Offer II 010. 和为 k 的子数组

题目链接

力扣

题目描述

给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。

示例 1:

输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况
示例 2:

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

提示:

1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107

解题思路

因为本题允许负数,所以滑动窗口行不通。

前缀和的解题思想

前缀和的题目解题思维比较固定,即当我们循环数组到下标N时,需要用到数组前N-1项的计算的结果(这里不一定非要是和,也可能是积等),此时我们就该考虑是否应该通过计算数组循环过程中的累计值的方式简化解题,如此便有了前缀和的解题思想。

了解了思想,下来就该考虑,这个累计的结果我们该通过什么方式保存起来呢?

1.题目明确要求不允许使用额外空间的,直接原地修改数组
2.不限制空间复杂度时,最好额外开辟空间计算,避免数据污染
3.计算时如果每次只需要获取前一次的累计结果,可以通过数组的方式存储每次获取数组末尾元素的值
4.如果每次计算需要获取前几次或更多次的结果进行对比时,推荐哈希表的方式,这样可以压缩时间复杂度

分析

这道题目非常简洁,就是求数组中何为整数k的连续子数组个数。
如果这道题的取值没有负数,那就是标准的滑窗问题,但因为有了负数,滑窗思想不能用了。
通过分析,这道题应该属于我们上面列举四种情况的最后一种。具体思路如下:

1.初始化一个空的哈希表和pre_sum=0的前缀和变量
2.设置返回值ret = 0,用于记录满足题意的子数组数量
3.循环数组的过程中,通过原地修改数组的方式,计算数组的累加和
4.将当前累加和减去整数K的结果,在哈希表中查找是否存在
5.如果存在该key值,证明以数组某一点为起点到当前位置满足题意,ret加等于将该key值对应的value
6.判断当前的累加和是否在哈希表中,若存在value+1,若不存在value=1
7.最终返回ret即可


但在这里要注意刚才说到的前缀和边界问题。
我们在计算这种场景时,需要考虑如果以数组nums[0]为开头的连续子数组就满足题意呢?
此时候我们的哈希表还是空的,没办法计算前缀和!所以遇到这类题目,都需要在哈希表中默认插入一个{0:1}的键值对,
用于解决从数组开头的连续子数组满足题意的特殊场景。

代码

def subarraySum(nums: list[int], k: int) -> int:
    ret = pre_sum = 0
    pre_dict = {0: 1}
    for i in nums:
        pre_sum += i
        ret += pre_dict.get(pre_sum - k, 0)
        pre_dict[pre_sum] = pre_dict.get(pre_sum, 0) + 1
    return ret

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值