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的子数组

相关推荐
我命由我1234528 分钟前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list
励志要当大牛的小白菜2 小时前
ART配对软件使用
开发语言·c++·qt·算法
qq_513970442 小时前
力扣 hot100 Day56
算法·leetcode
武子康3 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
PAK向日葵3 小时前
【算法导论】如何攻克一道Hard难度的LeetCode题?以「寻找两个正序数组的中位数」为例
c++·算法·面试
爱喝矿泉水的猛男5 小时前
非定长滑动窗口(持续更新)
算法·leetcode·职场和发展
YuTaoShao5 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw6 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨6 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
YouQian7726 小时前
Traffic Lights set的使用
算法