LeetCode hot100:560 和为k的子数组:快速统计法

问题描述:

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

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

示例1:

**输入:**nums = 1,1,1, k = 2

**输出:**2

**解释:**和为 2 的子数组有 1,1 (索引 0-1) 和 1,1 (索引 1-2)

示例2:

输入: nums = 1,2,3, k = 3
输出: 2
**解释:**和为 3 的子数组有 1,2 (索引 0-1) 和 3 (索引 2-2)

解决方法:

方法一:暴力枚举

思路:枚举所有的子数组,计算它们的和,统计等于k的个数。

python 复制代码
def subarraySum_brute_force(nums, k):
    count = 0
    n = len(nums)
    # 枚举所有子数组的起始位置
    for start in range(n):
        current_sum = 0
        # 枚举所有子数组的结束位置
        for end in range(start, n):
            # 计算子数组 nums[start..end] 的和
            current_sum += nums[end]
            # 如果和等于 k,计数加 1
            if current_sum == k:
                count += 1
    return count

复杂度分析:

  • 时间复杂度:O(n²) 双层循环枚举所有子数组
  • 空间复杂度:O(1) 只使用了常数空间

评价:数据量小时可以使用,对于数据规模过大时不高效。

方法二:前缀和+哈希表

思路:利用前缀和技巧(sum i : j = sum j - sum i - 1 ),通过哈希表记录之前出现过的前缀和及其次数,从而在 O(1) 时间内判断是否存在满足条件的子数组。

python 复制代码
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        from collections import defaultdict
        #创建前缀和计数字典 记录每个前缀和出现的次数 sum[i:j] = sum[j] - sum[i-1]
        prefix_count = defaultdict(int)
        #初始化
        prefix_count[0] = 1
        current_sum = 0
        count = 0
        #遍历数组元素
        for num in nums:
            #更新当前前缀和
            current_sum += num
            #检查是否存在某个前缀和等于 current_sum - k
            #若存在 从那个位置到当前位置子数组和为k
            if current_sum - k in prefix_count:
                #更新计数 增加的数量等于该前缀和出现的次数
                count += prefix_count[current_sum - k]
            #将当前前缀和计数加1 记录到字典
            prefix_count[current_sum] += 1
        return count    

复杂度分析:

  • 时间复杂度:O(n) 只需遍历数组一次
  • 空间复杂度:O(n) 最坏情况下需要存储 n 个不同的前缀和

评价:最优解。

问题详解:

1、前缀和+哈希表算法步骤:

  • 使用哈希表记录每个前缀和出现的次数;

  • 初始化前缀和为 0 出现 1 次(对应空数组);

  • 遍历数组,累计当前前缀和;

  • 检查 current_sum - k 是否在哈希表中;

  • 更新哈希表中当前前缀和的计数。

2、为什么初始化 prefix_count 0 = 1:

当数组的第一个元素就是所找的k时,此时 current_sum - k = 0;若没有初始化 prefix_count 0 = 1,就会错过这个子数组。

3、为什么 count += prefix_countcurrent_sum - k而不是count += 1:

因为同一前缀和的结果可能出现多次,每次所对应的位置不同。

例如 nums = 4,1,2,3,0,6,2,4 k = 6。

总结:

| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
| 暴力枚举 | O(n²) | O(1) | 实现简单 | 数据量大时效率低 |

前缀和+哈希表 O(n) O(n) 最优解,效率高 需要额外空间
  1. 前缀和技巧可以将子数组和问题转化为两数之差问题;

  2. 初始化 prefix_count 0 = 1 是处理边界情况的关键。

相关推荐
凯瑟琳.奥古斯特8 分钟前
力扣1015C++解法技巧
c++·算法·leetcode·链表·职场和发展
泡茶喝茶写代码14 分钟前
A股量化策略回测实战:从行情数据到绩效评估(第 13 篇):放量突破策略
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口
seowmt16 分钟前
GEO效果该什么时候看数据:从立项到复盘的时间线复盘
算法·ip·seo·geo·faq
悠仁さん17 分钟前
【算法C++】双指针(一)
数据结构·c++·算法
文丑颜不良啊18 分钟前
LeetCode626~650题目解析
java·leetcode
小豆庄25 分钟前
本地视频脱敏的追踪系统踩坑——车牌过滤、转场误判与ID冲突排查
人工智能·算法·目标检测·音视频·视频·敏捷流程·纹理贴图
忆挽篱笙歌26 分钟前
进程替换函数与shenll命令行解释器
前端·javascript·算法
cxyxixiy27 分钟前
数智码力:数据核对不用人工比对,Python 快速完成多表格差异校验
开发语言·python·学习
YukiRinLL28 分钟前
字符串存储与 BF、KMP 匹配算法
数据结构·算法
小超人诞生日记33 分钟前
Linux:环境变量 & 进程虚拟地址空间
linux·算法