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

相关推荐
luj_17686 小时前
残熵算法实时化三大瓶颈突破
c语言·开发语言·网络·经验分享·算法
充钱大佬7 小时前
Python测试基础教程
python·log4j·apache
mCell7 小时前
你以为短链接只是 Hash + 301/302?
后端·算法·架构
KaMeidebaby8 小时前
卡梅德生物技术快报|抗体亲和力成熟工业化调控新机制:差异性浆细胞增殖工艺优化思路
java·开发语言·人工智能·算法·机器学习·架构·spark
luj_17689 小时前
心形曲线轨迹控制三大关键技术
c语言·开发语言·c++·经验分享·算法
初心丨哈士奇9 小时前
Python 四大基础容器|列表篇
python
tmlx3I0819 小时前
高光谱拼接算法(六)RANSAC 误匹配剔除
人工智能·算法·机器学习
不相心 -w-9 小时前
基础-滑动窗口-(定长 | 不定长)
算法
醉城夜风~10 小时前
Java详解经典算法题:接雨水(三种实现方案+原理剖析)
java·开发语言·算法
明理的信封10 小时前
AI 基础设施的“去 Python 化“:Rust 与 C# 的两条替代路径
人工智能·python·rust