news 2026/3/4 5:53:53

【每日算法】LeetCode 560. 和为 K 的子数组

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【每日算法】LeetCode 560. 和为 K 的子数组

对前端开发者而言,学习算法绝非为了“炫技”。它是你从"页面构建者"迈向"复杂系统设计者"的关键阶梯。它将你的编码能力从"实现功能"提升到"设计优雅、高效解决方案"的层面。从现在开始,每天投入一小段时间,结合前端场景去理解和练习,你将会感受到自身技术视野和问题解决能力的质的飞跃。------ 算法:资深前端开发者的进阶引擎

LeetCode 560. 和为 K 的子数组:前缀和的精妙应用

1. 题目描述

给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的连续子数组的个数。

示例 1:

输入:nums = [1,1,1], k = 2 输出:2 解释:[1,1] 与 [1,1] 为两种不同的情况(注意:虽然值相同,但索引位置不同)

示例 2:

输入:nums = [1,2,3], k = 3 输出:2 解释:[1,2] 和 [3]

约束条件:

  • 数组长度范围:1 <= nums.length <= 2 * 10⁴
  • 数组元素范围:-1000 <= nums[i] <= 1000
  • k 的范围:-10⁷ <= k <= 10⁷

2. 问题分析

2.1 问题核心

这个问题要求统计数组中连续子数组的和等于给定值k的个数。这是一个典型的子数组求和问题,需要特别注意:

  • 子数组必须是连续的
  • 数组元素可以是负数,这增加了问题的复杂性
  • 需要考虑空数组吗?题目没有明确说明,但根据示例,至少需要包含一个元素

2.2 前端视角的类比

在前端开发中,类似的问题场景包括:

  • 统计页面中连续点击次数达到特定阈值的情况
  • 计算用户行为序列中特定模式的出现次数
  • 分析性能监控数据中连续时间段内指标达标的情况

3. 解题思路

3.1 思路演进

3.1.1 暴力枚举法

最直观的想法是枚举所有可能的子数组,计算它们的和,统计等于k的数量。

3.1.2 前缀和优化

暴力法的时间复杂度为 O(n²),对于 2×10⁴ 的数据量会超时。我们需要更高效的方法。

前缀和(Prefix Sum)概念
前缀和是一种预处理技术,通过预先计算并存储数组的前缀和,可以在 O(1) 时间内计算任意子数组的和。

定义前缀和数组preSum,其中preSum[i]表示nums[0] + nums[1] + ... + nums[i-1]的和。

那么子数组nums[i..j]的和可以表示为:

sum(nums[i..j]) = preSum[j+1] - preSum[i]
3.1.3 哈希表优化

对于每个j,我们需要找到有多少个i满足preSum[i] = preSum[j+1] - k。使用哈希表可以在 O(1) 时间内完成查找。

核心公式

preSum[j+1] - preSum[i] = k => preSum[i] = preSum[j+1] - k

3.2 复杂度分析

方法时间复杂度空间复杂度是否推荐
暴力枚举O(n²)O(1)不推荐,会超时
前缀和+哈希表O(n)O(n)推荐,最优解

4. 各思路代码实现

4.1 暴力枚举法(不推荐,仅用于理解)

/** * 暴力枚举法 * @param {number[]} nums * @param {number} k * @return {number} */varsubarraySumBruteForce=function(nums,k){letcount=0;constn=nums.length;for(leti=0;i<n;i++){letsum=0;for(letj=i;j<n;j++){sum+=nums[j];if(sum===k){count++;}}}returncount;};

4.2 前缀和+哈希表法(最优解)

/** * 前缀和+哈希表法(最优解) * @param {number[]} nums * @param {number} k * @return {number} */varsubarraySum=function(nums,k){// 哈希表:键为前缀和,值为该前缀和出现的次数constmap=newMap();// 初始化:前缀和为0出现了1次(空数组的情况)map.set(0,1);letcount=0;letprefixSum=0;for(leti=0;i<nums.length;i++){// 计算当前前缀和prefixSum+=nums[i];// 如果存在某个前缀和等于 currentPrefixSum - k// 说明从那个位置到当前位置的子数组和为 kif(map.has(prefixSum-k)){count+=map.get(prefixSum-k);}// 更新当前前缀和出现的次数map.set(prefixSum,(map.get(prefixSum)||0)+1);}returncount;};

4.3 带详细注释的版本(便于理解)

/** * 前缀和+哈希表法(详细注释版) * @param {number[]} nums * @param {number} k * @return {number} */varsubarraySumWithComments=function(nums,k){// 哈希表:存储前缀和及其出现次数// 为什么需要这个哈希表?// 我们要找的是:prefixSum[j] - prefixSum[i] = k// 即:prefixSum[i] = prefixSum[j] - k// 所以对于每个j,我们需要知道之前有多少个i满足这个条件constprefixSumCount=newMap();// 为什么要初始化前缀和为0出现了1次?// 考虑整个数组从开头到某个位置的子数组和为k的情况// 即:prefixSum[j] - 0 = k,这时候prefixSum[i]为0(i为-1,空数组)prefixSumCount.set(0,1);letcurrentSum=0;// 当前前缀和letresult=0;// 结果计数for(leti=0;i<nums.length;i++){// 计算到当前位置的前缀和currentSum+=nums[i];// 核心逻辑:如果存在一个前缀和等于 currentSum - k// 那么从那个位置到当前位置的子数组和就是k// 例如:nums = [1, 2, 3], k = 3// 当i=2时,currentSum = 6// currentSum - k = 3,如果之前出现过前缀和3,那么从那个位置到当前位置的和就是3consttarget=currentSum-k;if(prefixSumCount.has(target)){// 可能有多个位置的前缀和都等于target,所以都要加上result+=prefixSumCount.get(target);}// 更新当前前缀和的出现次数// 这里使用 || 0 来处理undefined的情况(如果该前缀和之前没出现过)prefixSumCount.set(currentSum,(prefixSumCount.get(currentSum)||0)+1);}returnresult;};

5. 各实现思路的复杂度、优缺点对比

5.1 对比表格

实现方法时间复杂度空间复杂度优点缺点适用场景
暴力枚举法O(n²)O(1)1. 思路直观简单
2. 不需要额外空间
1. 效率低下,n=20000时会超时
2. 不适合大数据量
小规模数据(n<1000)或教学演示
前缀和+哈希表O(n)O(n)1. 时间复杂度最优
2. 能处理包含负数的情况
3. 适合大规模数据
1. 需要额外O(n)空间
2. 逻辑相对复杂
大规模数据处理、生产环境推荐使用

5.2 详细分析

5.2.1 暴力枚举法
  • 时间复杂度分析

    • 外层循环:n次
    • 内层循环:平均n/2次
    • 总复杂度:O(n²)
    • 当n=20000时,操作次数约2亿次,明显超时
  • 空间复杂度:O(1),只使用了常数级别的额外空间

5.2.2 前缀和+哈希表法
  • 时间复杂度分析

    • 单次遍历数组:O(n)
    • 每次操作哈希表:平均O(1)
    • 总复杂度:O(n)
    • 当n=20000时,操作次数约2万次,效率极高
  • 空间复杂度

    • 最坏情况下,每个前缀和都不同,需要存储n个键值对
    • 空间复杂度:O(n)

6. 总结与前端应用场景

6.1 核心要点总结

  1. 前缀和思想:将子数组求和问题转化为前缀和之差的问题
  2. 哈希表优化:通过哈希表记录前缀和出现次数,实现O(1)时间查找
  3. 边界处理:注意初始化前缀和为0的情况(对应空子数组)
  4. 负数处理:由于数组元素可能为负数,不能使用双指针滑动窗口法

6.2 实际应用场景(前端视角)

6.2.1 性能监控与分析
// 监控连续时间段内API错误率达到阈值的情况consterrorRates=[0.1,0.2,0.05,0.3,0.15,0.25];constthreshold=0.5;// 统计连续时间段内错误率总和超过阈值的时间段数量functioncountErrorSpikes(errorRates,threshold){constmap=newMap();map.set(0,1);letcount=0;letprefixSum=0;for(letrateoferrorRates){prefixSum+=rate;if(map.has(prefixSum-threshold)){count+=map.get(prefixSum-threshold);}map.set(prefixSum,(map.get(prefixSum)||0)+1);}returncount;}
6.2.2 用户行为分析
// 分析用户连续操作序列// 例如:统计用户连续点击次数达到特定模式的情况constuserActions=['click','scroll','click','hover','click'];consttargetPattern=2;// 连续click的次数functioncountActionPatterns(actions,targetAction,targetCount){constmap=newMap();map.set(0,1);letcount=0;letcurrentStreak=0;for(letactionofactions){// 如果是目标行为,streak加1,否则重置为-1(或其他负值)currentStreak+=(action===targetAction?1:-1);// 查找是否有位置使得连续目标行为次数等于targetCountif(map.has(currentStreak-targetCount)){count+=map.get(currentStreak-targetCount);}map.set(currentStreak,(map.get(currentStreak)||0)+1);}returncount;}
6.2.3 数据处理与可视化
// 在数据可视化中,统计连续时间段内数据超过阈值的情况classDataAnalyzer{constructor(){this.prefixSumMap=newMap();}// 实时数据流处理processDataStream(dataStream,threshold){constresult=[];letprefixSum=0;letmap=newMap([[0,[-1]]]);// 存储前缀和及其出现的位置for(leti=0;i<dataStream.length;i++){prefixSum+=dataStream[i];// 查找满足条件的位置consttarget=prefixSum-threshold;if(map.has(target)){constpositions=map.get(target);for(letposofpositions){result.push([pos+1,i]);// 子数组的起始和结束索引}}// 更新哈希表if(!map.has(prefixSum)){map.set(prefixSum,[]);}map.get(prefixSum).push(i);}returnresult;}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/1 4:20:25

5大亮点解析:Launcher3打造极致原生安卓桌面体验

5大亮点解析&#xff1a;Launcher3打造极致原生安卓桌面体验 【免费下载链接】Launcher3 The Launcher3 fork known as "Rootless Pixel Launcher" 项目地址: https://gitcode.com/gh_mirrors/la/Launcher3 Launcher3作为一款备受推崇的开源Android启动器&…

作者头像 李华
网站建设 2026/3/4 5:11:57

如何快速掌握POV-Ray:射线追踪渲染完整指南

如何快速掌握POV-Ray&#xff1a;射线追踪渲染完整指南 【免费下载链接】povray The Persistence of Vision Raytracer: http://www.povray.org/ 项目地址: https://gitcode.com/gh_mirrors/po/povray POV-Ray&#xff08;Persistence of Vision Raytracer&#xff09;是…

作者头像 李华
网站建设 2026/2/28 10:31:02

CVAT权限管理全攻略:从零构建安全高效的标注团队协作体系

CVAT权限管理全攻略&#xff1a;从零构建安全高效的标注团队协作体系 【免费下载链接】cvat Annotate better with CVAT, the industry-leading data engine for machine learning. Used and trusted by teams at any scale, for data of any scale. 项目地址: https://gitco…

作者头像 李华
网站建设 2026/2/28 0:32:54

Kubernetes Service详解:实现服务发现与负载均衡

. Service概念引入k8s之部署Deployment章节我们介绍RS以及Deployment&#xff0c;Deployment提供了pod的管理方式&#xff0c;以及通过副本控制器RC保证集群中pod的数量保持为指定数量。同时Deployment还提供了相关升级、回滚、更新速度、灰度发布等功能。那么pod之间怎么进行访…

作者头像 李华
网站建设 2026/3/2 18:50:13

k8s使用kubectl报错

k8s使用kubectl报错&#xff1a;[rootmaster01 ~]# kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port?检查kubelet状态&#xff0c;发现没启动成功[rootnode02 ~]# kubectl status kubelet E1217 23:04:…

作者头像 李华
网站建设 2026/3/1 8:14:25

DuckDB Java集成实战:从零构建高性能数据分析应用

DuckDB Java集成实战&#xff1a;从零构建高性能数据分析应用 【免费下载链接】duckdb DuckDB is an in-process SQL OLAP Database Management System 项目地址: https://gitcode.com/GitHub_Trending/du/duckdb 传统关系型数据库在数据分析场景中常常面临性能瓶颈&…

作者头像 李华