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

相关推荐
地平线开发者6 小时前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮6 小时前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者7 小时前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考7 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
孟健9 小时前
Karpathy 用 200 行纯 Python 从零实现 GPT:代码逐行解析
python
HXhlx10 小时前
CART决策树基本原理
算法·机器学习
码路飞11 小时前
写了个 AI 聊天页面,被 5 种流式格式折腾了一整天 😭
javascript·python
Wect11 小时前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
颜酱12 小时前
单调队列:滑动窗口极值问题的最优解(通用模板版)
javascript·后端·算法
曲幽13 小时前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers