leetcode刷题——560、和为k的子数组(前缀和思想和哈希表)

本文详细解析了LeetCode上子数组和为K的问题,通过前缀和思想结合哈希表的方法,有效地解决了暴力遍历带来的超时问题。文章通过实例展示了算法的具体实现过程,对于理解并解决类似问题提供了清晰的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、原题链接

  [和为k的子数组](https://leetcode-cn.com/problems/subarray-sum-equals-k/)

二、思路

  直接暴力遍历的话会超时。因此使用前缀和思想和哈希表结合的方式去解这道题。具体解释来说:
  1、程序中定义前缀和数组prefix_sum,prefix_sum[i]用于记录数组nums[0]~nums[i]的和;
  2、我们需要找到数组中和为k的连续子数组,用前缀和数组来解释的话就是:在数组中找是否存在下标i和j,i小于j,使得prefix_sum[j]-prefix_sum[i]=k。
  3、在遍历数组nums的过程中,对于当前的元素item而言,计算出对应的前缀和prefix_sum[j],那么求解是否有以item结尾的连续子数组就等价于判断是否存在一个前缀和为prefix[j]-k。
  4、为何要结合哈希表?题目中指出需要找到“连续的子数组的个数”,为了返回这个个数,我们使用哈希表来处理。定义hashtable,其中的key就是我们求得的前缀和,value则是对应的前缀和出现的次数。
  具体到程序中,借鉴前缀和的思想,我们只需要定义一个变量始终记录当前索引处的前缀和prefix_sum,对这一前缀和做以下几种情况的处理:
  1、判断前缀和prefix_sum的值是否为k,是的话将待返回的个数cnt+1;
  2、判断哈希表hashtable中是否有一项的key为prefix_sum-k,有的话更新cnt的值为cnt+hashtable[prefix_sum-k]
  接下来要做的就是将prefix_sum保存下来,那么保存时就会有两种情况:
  1、hashtable中有一项的值为prefix_sum,表明我们已经找到过若干连续子数组的和prefix_sum,此时需要更新对应的value;
  2、hashtable中没有任何一项的key为prefix_sum,此时将(key=prefix_sum, value=1)送入哈希表即可。


  参考代码如下:
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        # 基于前缀和思想,采用哈希表处理
        hashtable = {}
        prefix_sum = cnt = 0  # prefix_sum用于记录前缀和,cnt记录符合条件的子数组的个数
        for val in nums:
            prefix_sum += val
            # 如果当前的前缀和等于k,将cnt+1
            if prefix_sum == k:
                cnt +=1
            # 检查哈希表中是否存在prefix_sum-k
            if prefix_sum-k in dic:
                cnt += hashtable[prefix_sum-k]
            # 如果prefix_sum存在于哈希表,则更新对应的value;否则设置value为1
            if prefix_sum in hashtable:
                hashtable[prefix_sum] += 1
            else:
                hashtable[prefix_sum] = 1
        return cnt

  以下面这个例子来简单分析前两步,定义k=3,数组nums如下:
1234-2212

  遍历数组的过程中维持哈希表hashtable,将hashtable初始化为{},数组下标为index。
  index=0时,prefix_sum=1,1 ≠3 且1-3=-2不在hashtable中,,将key=1,value=1送入哈希表,此时hashtable={1:1};
  index=1时,prefix_sum=3,3 =3,将cnt+1,,0不在hashtable中,将key=3,value=1送入哈希表,此时hashtable={1:1,3:1};



欢迎评论,对您有帮助还请点个赞
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值