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

相关推荐
固定资产管理系统软件11 分钟前
商务局RFID固定资产管理系统的应用价值与落地要点解析
大数据·python
叩码以求索1 小时前
浅谈:前序遍历反转法求解N叉树的后序遍历
算法
lancyu1 小时前
关于多轮对话机器人的上下文Token优化和解决方案
人工智能·python·深度学习·机器学习·chatgpt·机器人·prompt
草莓橙子碗2 小时前
Claude 使用指南
开发语言·python
工具分享2 小时前
陪跑跟品爆单AI选品助手,高效跟品会赔本吗?
人工智能·python
COOLMO研究AI2 小时前
Python 如何实现 AI API 的提示词(Prompt)版本管理与热更新
人工智能·python·prompt
老郑聊AI业财智造2 小时前
Transformer 技术架构与源码分析
人工智能·python·深度学习·语言模型·架构·transformer·软件工程
北风toto2 小时前
中缀、前缀、后缀表达式
算法·软件设计师
程序员三藏2 小时前
自动化测试用例编写详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
听取WA声一片(无恶意)2 小时前
CSP-J/CSP-S 深度优先搜索(DFS)完全讲义
c++·算法·深度优先