LeetCode LCR 010 和为 K 的子数组 (Java)

两种解法详解:暴力枚举与前缀和+哈希表寻找和为k的子数组

在解决数组中和为k的连续子数组个数的问题时,我们可以采用不同的方法。本文将详细解析两种常见的解法:暴力枚举法和前缀和结合哈希表的方法,分析它们的思路、优缺点及适用场景。


问题描述

给定一个整数数组 nums 和一个整数 k,要求找到所有和为 k 的连续子数组的个数。

示例

复制代码
输入:nums = [1,1,1], k = 2
输出:2
解释:[1,1](前两个元素)和 [1,1](后两个元素)各为一种情况。

解法一:暴力枚举法

思路分析

暴力枚举法的核心思想是遍历所有可能的子数组,计算它们的和是否等于 k。具体来说:

  • 外层循环固定子数组的起始位置 start
  • 内层循环从 start 出发,逐步扩展子数组的结束位置 j,并累加元素和。
  • 当子数组和等于 k 时,计数器增加。

代码实现

java 复制代码
public static int subarraySum_1(int[] nums, int k) {
    int count = 0;
    for (int start = 0; start < nums.length; start++) {
        int sum = 0;
        for (int j = start; j < nums.length; j++) {
            sum += nums[j];
            if (sum == k) {
                count++;
            }
        }
    }
    return count;
}

复杂度分析

  • 时间复杂度 :O(n²)。双重循环遍历所有子数组,对于长度为 n 的数组,共有 n(n+1)/2 个子数组。
  • 空间复杂度:O(1)。仅使用常数空间存储临时变量。

适用场景

适用于小规模数据(例如 n ≤ 1e3)。当 n 较大时(如 n = 2e4),暴力法会因时间复杂度过高而超时。


解法二:前缀和 + 哈希表

思路分析

该方法利用前缀和的性质和哈希表的快速查询特性,将时间复杂度优化至线性:

  1. 前缀和定义sum[i] 表示数组前 i 个元素的和。
  2. 关键观察 :若存在 sum[j] - sum[i] = k,则子数组 nums[i+1..j] 的和为 k
  3. 哈希表优化 :维护哈希表记录前缀和出现的次数。遍历时,若当前前缀和 sumsum - k 存在,则累加次数。

代码实现

java 复制代码
    public static int subarraySum_2(int[] nums, int k) {
        int count=0;    //记录结果
        int sum = 0;    //记录前缀和

        //HashMap,k:存储前缀和,V:存储前缀和出现的次数
        HashMap<Integer, Integer> map = new HashMap<>();

        //第一个数的前缀和为0
        map.put(0,1);

        for(int i=0;i<nums.length;i++){
            sum +=nums[i];

            //注意这一定是先去判断再添加,每个数都要去判断一下,第一个数的前缀和已经添加了,所以需要判断
            if(map.containsKey(sum-k)){
                count += map.get(sum-k);
            }

            //如何这个sum没出现过:v = 0+1,出现过:v = 原来v + 1;
            map.put(sum,map.getOrDefault(sum,0)+1);
        }
        return count;
    }

复杂度分析

  • 时间复杂度:O(n)。只需一次遍历数组,哈希表查询和插入操作均为 O(1)。
  • 空间复杂度 :O(n)。哈希表最多存储 n 个不同的前缀和。

关键点

  • 哈希表初始化 :预先放入 (0, 1),处理以第一个元素开头的子数组和为 k 的情况。
  • 负数处理:数组中可能存在负数,导致前缀和重复出现,哈希表需正确统计次数。

方法对比

方法 时间复杂度 空间复杂度 适用场景
暴力枚举法 O(n²) O(1) 小规模数据
前缀和 + 哈希表法 O(n) O(n) 大规模数据

总结

  • 暴力枚举法思路简单,但仅适用于小规模数据。
  • 前缀和+哈希表通过空间换时间,将复杂度降至线性,是处理大规模数据的高效方法。
  • 特别注意哈希表的初始化与更新逻辑,确保正确处理所有边界情况。

相关题目LeetCode 560. 和为K的子数组

相关推荐
天若有情6732 分钟前
打破思维定式!C++参数设计新范式:让结构体替代传统参数列表
java·开发语言·c++
初晴や3 分钟前
【C++】图论:基础理论与实际应用深入解析
c++·算法·图论
李泽辉_4 分钟前
深度学习算法学习(五):手动实现梯度计算、反向传播、优化器Adam
深度学习·学习·算法
亲爱的非洲野猪7 分钟前
从ReentrantLock到AQS:深入解析Java并发锁的实现哲学
java·开发语言
wheelmouse77889 分钟前
如何设置VSCode打开文件Tab页签换行
java·python
yangminlei11 分钟前
Spring Boot——日志介绍和配置
java·spring boot
廋到被风吹走18 分钟前
【Spring】Spring Boot Starter设计:公司级监控SDK实战指南
java·spring boot·spring
李泽辉_19 分钟前
深度学习算法学习(一):梯度下降法和最简单的深度学习核心原理代码
深度学习·学习·算法
꧁Q༒ོγ꧂22 分钟前
算法详解---大纲
算法
码头整点薯条23 分钟前
启动报错:Invalid value type for attribute ‘factoryBeanObjectType‘ 解决方案
java