python-leetcode 10.和为K的子数组

题目:

给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的子数组的个数

子数组是数组中元素的连续非空序列

方法一:暴力枚举法

枚举nums的所有子数组,统计其中和为k的子数组个数。

考虑以i结尾和为k的连续子数组的个数,统计符合条件的下标j的个数,其中0<=j<=i,且这个子数组的和为k。可以枚举[0,,,i]里所有的下标j来判断是否符合条件。

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        count=0  #记录和为k的子数组的个数,初始值为0
        for start in range(len(nums)): #遍历数组中的每一个元素作为子数组的起始位置
            sum=0  #表示从start到当前end索引位置的子数组的和
            for end in range(start,-1,-1): #遍历从start到0的所有索引
                sum+=nums[end]
                if sum==k:  #检查子数组的是否等于目标值k
                    count+=1
        return count  #返回和为k的子数组的数目


        

时间复杂度:O(n2)其中 n 为数组的长度。枚举子数组开头和结尾需要 O(n2) 的时间,其中求和需要 O(1) 的时间复杂度,因此总时间复杂度为 O(n2)。

空间复杂度:O(1)只需要常数空间存放若干变量

测试可以通过,但是提交会超过时间限制

方法二:前缀和+哈希表优化

可以使用前缀和和数组进一步优化方法一。定义前缀和数组pre使得pre[i]为nums[0],nums[i]中所有数的和,则pre[i]可以从pre[i-1]得到,即pre[i]=pre[i-1]+nums[i]

那么[j,,i]这个子数组的和为k,这个条件可以转换为pre[i]-pre[j-1]=k.简单移项可得到符合条件的下标j,需要满足pre[j-1]==pre[i]-k。所以可以考虑以i结尾的和为k的连续子数组个数时只要统计有多少个前缀和为pre[i]-k的pre[j]即可。

建立哈希表mp,以前缀和pre[i]为键,出现的次数为对应的值,记录pre[i]出现的次数,从左到右边更新mp边计算答案,那么以i结尾的答案mp[pre[i]-k]即可在O(1)时间内得到,最后的答案即为所有下标结尾和为k的子数组个数之和。

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        count=0 #初始化和为k的数组的数量
        sum=0 #初始化当前子数组的和
        map={0:1} #字典,记录前缀和出现的次数,考虑了空数组的情况
        for num in nums:
            sum +=num  #对于每个元素,更新当前子数组的和
            if sum-k in map:  #sum-k存在,意味着之前有一个子数组的和为sum -k,而当前的和为 sum,因此这两个子数组的和加起来就是 k
                count +=map[sum-k]#如果sum-k在map中出现过,表示从某些位置到当前元素子数组和为k
            map[sum]=map.get(sum,0)+1 #更新字典 map 中当前和 sum 的计数
                #map.get(sum,0)的作用是,如果字典中没有键sum,则返回默认值 0,否则返回当前sum的计数然后将计数加 1
        return count

时间复杂度:O(n)其中 n 为数组的长度。我们遍历数组的时间复杂度为 O(n),中间利用哈希表查询删除的复杂度均为 O(1),因此总时间复杂度为 O(n)

空间复杂度:O(n)其中 n 为数组的长度。哈希表在最坏情况下可能有 n 个不同的键值,因此需要 O(n) 的空间复杂度

### LeetCode 'Subarray Sum Equals K' 的 Python 解法 以下是针对该问题的一个高效解决方案,时间复杂度为 \(O(n)\),空间复杂度为 \(O(n)\)[^3]。 此方法的核心思想是利用前缀以及哈希表来记录之前计算过的累积及其出现次数。通过这种方式可以快速判断当前累积减去目标值 \(k\) 是否已经存在于之前的累积中。 #### 实现代码 ```python class Solution: def subarraySum(self, nums, k): """ :type nums: List[int] :type k: int :rtype: int """ count = {0: 1} # 初始化哈希表,表示累积为0的情况出现了1次 cur_sum = 0 # 当前累积初始化为0 result = 0 # 符合条件的子数组数量 for num in nums: cur_sum += num # 更新当前累积 # 如果 (cur_sum - k) 存在于哈希表中,则找到符合条件的子数组 if (cur_sum - k) in count: result += count[cur_sum - k] # 将当前累积加入到哈希表中,更新其出现次数 if cur_sum in count: count[cur_sum] += 1 else: count[cur_sum] = 1 return result # 返回最终的结果 ``` 上述实现的关键点如下: - 使用 `count` 字典存储累积及其对应的出现次数。 - 遍历过程中不断累加当前元素至 `cur_sum` 中,并检查 `(cur_sum - k)` 是否已存在于字典中。如果存在,则表明找到了若干个满足条件的连续子数组[^4]。 - 时间复杂度主要由单层循环决定,因此整体效率较高。 ### 示例运行 对于输入 `nums = [1, 1, 1]`, `k = 2`: 执行过程如下: - 初始状态:`cur_sum=0`, `result=0`, `count={0: 1}` - 处理第一个数 `num=1`: - 更新 `cur_sum=1` - 检查 `cur_sum-k=-1` 不在 `count` 中 - 更新 `count={0: 1, 1: 1}` - 处理第二个数 `num=1`: - 更新 `cur_sum=2` - 检查 `cur_sum-k=0` 在 `count` 中,增加 `result+=1` - 更新 `count={0: 1, 1: 1, 2: 1}` - 处理第三个数 `num=1`: - 更新 `cur_sum=3` - 检查 `cur_sum-k=1` 在 `count` 中,增加 `result+=1` - 更新 `count={0: 1, 1: 1, 2: 1, 3: 1}` 最终返回结果为 `result=2`[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值