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_count[current_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 是处理边界情况的关键。

相关推荐
用户3721574261353 小时前
Python 高效实现 Excel 与 TXT 文本文件之间的数据转换
python
在等晚安么3 小时前
力扣面试经典150题打卡
java·数据结构·算法·leetcode·面试·贪心算法
AndrewHZ3 小时前
【图像处理基石】图像滤镜的算法原理:从基础到进阶的技术解析
图像处理·python·opencv·算法·计算机视觉·滤镜·cv
lxmyzzs3 小时前
【图像算法 - 30】基于深度学习的PCB板缺陷检测系统: YOLOv11 + UI界面 + 数据集实现
人工智能·深度学习·算法·yolo·缺陷检测
gihigo19984 小时前
基于萤火虫算法(FA)优化支持向量机(SVM)参数的分类实现
算法·支持向量机·分类
py有趣4 小时前
LeetCode算法学习之移动0
学习·算法·leetcode
lixinnnn.4 小时前
算法总结篇(枚举-分治)
算法·1024程序员节
百锦再4 小时前
Go与Python在AI大模型开发中的深度对比分析
java·开发语言·人工智能·python·学习·golang·maven
on_pluto_4 小时前
【基础复习3】决策树
算法·决策树·机器学习