news 2026/5/10 5:48:53

LeetCode 热题100:和为 K 的子数组(Java 实现详解)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 热题100:和为 K 的子数组(Java 实现详解)

LeetCode 热题100:和为 K 的子数组(Java 实现详解)

本文将深入剖析 LeetCode 第560题《和为 K 的子数组》,从暴力枚举到前缀和 + 哈希表优化,全面讲解如何在 O(n) 时间内高效统计连续子数组和为 k 的个数。内容涵盖解题思路、代码实现、复杂度分析、面试高频问题及实际应用场景。


📌 原题回顾

题目描述
给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的子数组的个数

子数组:数组中元素的连续非空序列

示例

输入:nums = [1,1,1], k = 2 输出:2 解释:[1,1](索引0~1)和 [1,1](索引1~2) 输入:nums = [1,2,3], k = 3 输出:2 解释:[1,2] 和 [3]

约束条件

  • 1 <= nums.length <= 2 * 10^4
  • -1000 <= nums[i] <= 1000
  • -10^7 <= k <= 10^7

🔍 原题分析

本题要求统计所有连续子数组中和等于 k 的数量

关键点:

  • 子数组必须连续
  • 元素可正可负,因此不能提前终止(负数可能使后续和再次等于 k);
  • 暴力法时间复杂度高,需寻找更优解。

常见误区:

  • 误用滑动窗口(仅适用于全正数或单调性场景);
  • 忽略前缀和中“0”的初始状态。

💡 答案构思

方法一:暴力枚举(O(n²))

对每个起始位置i,向左累加(或向右),检查是否存在子数组和为k

虽然可行,但面对n=2e4时,操作次数高达 2e8,可能超时。

方法二:前缀和 + 哈希表(O(n))✅ 推荐

核心思想
  • 定义前缀和prepre[i] = nums[0] + nums[1] + ... + nums[i]
  • 若存在子数组nums[j..i]满足sum = k,则:
    pre[i] - pre[j-1] = k ⇒ pre[j-1] = pre[i] - k
  • 因此,对于当前前缀和pre,只需知道之前有多少个前缀和等于pre - k
关键技巧
  • 使用HashMap记录每个前缀和出现的次数
  • 初始化map.put(0, 1):表示前缀和为 0 出现 1 次(对应空子数组,用于处理从索引 0 开始的子数组)。

✅ 完整答案(Java)

方法一:暴力枚举(不推荐,仅作对比)

publicclassSolution{publicintsubarraySum(int[]nums,intk){intcount=0;for(intstart=0;start<nums.length;start++){intsum=0;for(intend=start;end>=0;end--){sum+=nums[end];if(sum==k){count++;}}}returncount;}}

方法二:前缀和 + 哈希表(最优解)

importjava.util.HashMap;publicclassSolution{publicintsubarraySum(int[]nums,intk){intcount=0;intpre=0;// 当前前缀和HashMap<Integer,Integer>map=newHashMap<>();map.put(0,1);// 重要!前缀和为0出现1次(空子数组)for(intnum:nums){pre+=num;// 查找是否存在 pre - kif(map.containsKey(pre-k)){count+=map.get(pre-k);}// 更新当前前缀和的出现次数map.put(pre,map.getOrDefault(pre,0)+1);}returncount;}}

🧠 代码分析

  • map.put(0, 1):这是最容易忽略的点!
    例如nums = [3], k = 3,当pre = 3时,需要pre - k = 0,若 map 中没有 0,则会漏掉这个解。
  • 累加顺序:先查pre - k,再更新map,避免将当前前缀和自身计入(防止 j > i)。
  • 负数支持:由于允许负数,前缀和可能重复、递减,哈希表能正确处理。

⏱️ 时间复杂度 & 空间复杂度分析

方法时间复杂度空间复杂度说明
暴力枚举O(n²)O(1)双重循环,内层累加 O(1)
前缀和 + 哈希表O(n)O(n)单次遍历,哈希表最坏存 n 个不同前缀和

n = 2e4时,O(n) 与 O(n²) 性能差距巨大,后者可能超时。


❓ 问题解答(FAQ)

Q1:为什么不能用滑动窗口?
A:滑动窗口要求“窗口扩大时和单调增加”,但本题含负数,窗口扩大后和可能变小,无法保证单调性。

Q2:如果 k 很大(如 1e9),会影响哈希表吗?
A:不会。哈希表 key 是前缀和(int 范围内),与 k 大小无关,只与pre - k是否存在于 map 中有关。

Q3:能否用数组代替 HashMap?
A:不行。前缀和范围可能很大(如[-2e7, 2e7]),无法用数组索引,且有负数。


🚀 优化思路

本题的 O(n) 解法已是最优,但可注意以下工程细节:

  1. 使用getOrDefault避免 NPE;
  2. 避免重复计算pre - k,可缓存为变量;
  3. 考虑溢出:虽然题目未要求,但若nums[i]极大,可用longpre
// 防溢出版本(本题无需,但好习惯)longpre=0;Map<Long,Integer>map=newHashMap<>();

📚 数据结构与算法基础知识点回顾

知识点说明
前缀和(Prefix Sum)快速计算任意区间和:sum[i..j] = pre[j] - pre[i-1]
哈希表(HashMap)O(1) 插入/查询,用于记录历史状态频次
子数组 vs 子序列子数组必须连续,子序列可不连续
初始化边界条件map.put(0, 1)是解决“从头开始”子数组的关键

💬 面试官提问环节(模拟)

Q:如果数组全是正数,能否用双指针?
A:可以!此时前缀和单调递增,可用滑动窗口:

  • 若当前和 < k,右指针右移;
  • 若当前和 > k,左指针右移;
  • 若等于 k,计数并移动指针。

Q:如何修改代码以返回所有满足条件的子数组(而不仅是数量)?
A:需记录每个前缀和对应的索引列表,当pre - k存在时,遍历其索引列表生成子数组。但空间复杂度上升。

Q:如果要求子数组长度至少为 L,怎么改?
A:可在哈希表中存储<前缀和, Deque<索引>>,每次查询时只取索引 ≤ i - L 的项。


🛠️ 实际开发中的应用场景

  1. 金融交易系统:统计某段时间内累计收益等于目标值的交易区间;
  2. 日志分析:查找连续请求耗时总和等于阈值的时间窗口;
  3. 物联网数据流:检测传感器数据中是否存在累计偏差为 k 的时间段;
  4. 游戏开发:判断玩家连续得分是否达到某个奖励阈值。

🔗 相关题目推荐

题号题目关联点
LeetCode 560本题
LeetCode 523连续的子数组和前缀和 + 同余定理
LeetCode 525连续数组前缀和 + 0/1 平衡
LeetCode 974和可被 K 整除的子数组前缀和 + 模运算
LeetCode 724寻找数组的中心下标前缀和应用

📝 总结与延伸

本题是前缀和 + 哈希表的经典应用,展示了如何将 O(n²) 问题优化至 O(n)。

核心思想提炼:

  • 将“区间和”问题转化为“前缀和差值”问题;
  • 利用哈希表记录历史状态,实现 O(1) 查询;
  • 正确处理边界条件(如前缀和为 0)。

延伸思考:

  • 若数组动态更新(如支持单点修改),可使用树状数组(Fenwick Tree)线段树维护前缀和;
  • 若 k 为变量(多次查询),可预处理所有前缀和并排序,用二分查找(但本题 k 固定,哈希更优)。

掌握前缀和思想,你就拥有了处理“区间和”类问题的利器!

建议动手实现两种方法,对比性能差异,加深理解。

👉 如果你觉得本文对你有帮助,欢迎点赞、收藏、评论!也欢迎关注我的 CSDN 主页,获取更多高质量算法解析。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 12:17:07

OPPO手机发布会预热:用HeyGem生成高管讲话模拟视频

OPPO手机发布会预热&#xff1a;用HeyGem生成高管讲话模拟视频 在消费电子新品发布的前夜&#xff0c;时间就是流量。当各大品牌还在为高管档期、拍摄周期和多语言版本反复协调时&#xff0c;一场静悄悄的技术变革已经悄然改变了内容生产的规则——AI驱动的数字人视频&#xff…

作者头像 李华
网站建设 2026/5/9 0:28:56

揭秘PHP跨域难题:5分钟彻底搞懂同源策略与JSONP替代方案

第一章&#xff1a;PHP跨域问题的本质解析在现代Web开发中&#xff0c;前端与后端常部署于不同域名下&#xff0c;导致浏览器基于安全策略实施同源限制。当使用JavaScript发起跨域请求时&#xff0c;若服务器未正确配置响应头&#xff0c;浏览器将阻止响应数据的访问&#xff0…

作者头像 李华
网站建设 2026/5/7 23:46:42

【高并发缓存设计】:PHP + Redis集群架构的3个关键优化点

第一章&#xff1a;高并发缓存系统的设计背景与挑战在现代互联网应用中&#xff0c;用户请求量呈指数级增长&#xff0c;传统数据库在面对高频读写时往往成为性能瓶颈。缓存系统作为提升响应速度和降低数据库压力的核心组件&#xff0c;被广泛应用于电商、社交、金融等关键业务…

作者头像 李华
网站建设 2026/5/5 3:10:35

从单机到分布式:PHP WebSocket实时通信系统的3次架构演进之路

第一章&#xff1a;从单机到分布式&#xff1a;PHP WebSocket实时通信系统的3次架构演进之路在构建高并发实时应用的过程中&#xff0c;PHP WebSocket 系统经历了从单机部署到分布式架构的深刻变革。每一次演进都源于业务增长带来的性能瓶颈与扩展性挑战&#xff0c;推动着系统…

作者头像 李华
网站建设 2026/5/7 16:43:27

大文件上传性能提升10倍?:深度剖析PHP分片上传底层机制

第一章&#xff1a;大文件上传性能提升10倍&#xff1f;——重新审视PHP的极限在传统认知中&#xff0c;PHP常被认为不适合处理大文件上传&#xff0c;受限于内存限制、执行时间约束以及同步阻塞的I/O模型。然而&#xff0c;通过合理架构设计与底层优化&#xff0c;PHP完全可以…

作者头像 李华
网站建设 2026/5/7 21:49:16

PHP与区块链数据交互全解析(从零构建高性能查询系统)

第一章&#xff1a;PHP与区块链数据交互全解析&#xff08;从零构建高性能查询系统&#xff09;在去中心化应用日益普及的今天&#xff0c;PHP作为广泛使用的服务端语言&#xff0c;正逐步被用于对接区块链网络&#xff0c;实现链上数据的高效读取与处理。通过合理设计架构&…

作者头像 李华