当前位置: 首页 > news >正文

前缀和+哈希:和为K的子数组

题目描述:
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。

OJ链接

一开始看到这道算法题时,我首先想到的是前缀和+滑窗来解决,但是在实际构写滑窗循环时,发现很难兼顾到各种情况,因为这道算法题的数据范围是正负交替的。

在这里插入图片描述
使用滑动窗口,本质上是将O(n ^ 2)的时间复杂度优化成为O(n)。一般而言,滑动窗口的做法都是在暴力枚举的基础上优化而来的——通过一定的逻辑分析,舍弃掉大量无意义的枚举情况,进而优化时间复杂度。

但是,在这道题目,这样的数据范围之下,是没有办法用滑窗进行解决的,因为数据取值正负情况的不同,会带来优化逻辑的不同,而且目标和 K 也是可以正负取值的(想清楚这一点很重要)。

所以,在确认滑动窗口无法解决此道题目后,接下来介绍两种算法。

暴力枚举

我们可以先维护一个前缀和数组,这个前缀和数组使得原数组中任意一个子数组的和都能在O(1)的时间复杂度下求出,然后在暴力枚举每一个子数组。

暴力枚举每一个子数组时,通常按照一定的规律:以某个数为结尾,或者以某个数为开始。这两种枚举方案都可以确保枚举到所有的情况。

以下是提供的参考代码,其中枚举时选择以某个数为结尾这种方案。

    int subarraySum(vector<int>& nums, int k) {int sz = nums.size();vector<int> dp(sz + 1);for(int i = 1;i <= sz;i++)dp[i] = dp[i - 1] + nums[i - 1];int count = 0;for(int i = 1;i <= sz;i++)for(int j = 1;j <= i;j++)if(dp[i] - dp[j - 1] == k)count++;return count;}

非暴力枚举:前缀和+哈希

实际上,这道题目不需要用暴力枚举的算法。

我们来分析以下这道题目。题目要求我们找到一个和为k的非空子数组,首先这个非空子数组一定是以数组中的某个数为结尾的,也就是说,我们实际上要做的工作就是——对于原数组中的任意一个数,我们想要找到是否有一个和为k的子数组以之为结尾,就是在该数之前再找到一个数,使这两数之间的数和为k——再进一步转换,要使得这两数之间的和为k,既存在子数组在原数组中左半部分的数和为sum - k(sum是该子数组右边界所对应的前缀和)。

这样转换后,我们去找原数组中以某个数为结尾的和为k的子数组是否存在时,实质上就是去找该数之前所有数对应的前缀和中,有无等于sum - k,如果有,又存在几个(sum是该数所对应的前缀和).

我们当然可以遍历取查找sum - k,但是这样本质也是暴力枚举,想要在O(1)的时间复杂度内查找一个数是否存在,查找一个数存在几次,我们可以利用哈希表的结构。在这个哈希表中,前缀和为key值,该前缀和出现的次数则为value值。

另外,在这种做法中,不需要提前维护好一个前缀和数组,因为找以某数为结尾的子数组,只需要查找该数之前的前缀和是否存在sum - k,既当前状态只依赖于之前的状态,有点类似于动态规划问题中的滚动数组优化所以,我们可以一边迭代前缀和,以便维护好前缀和的哈希结构。

具体代码如下所示(在代码示例中,是以某个数为结尾进行构建的,若更改为以某个数为开始,也是可行的)

    int subarraySum(vector<int>& nums, int k) {unordered_map<int,int> hash;hash[0] = 1;//默认0的个数为1int count = 0;int sum = 0;for(auto& e : nums){sum += e;if(hash.count(sum - k))count += hash[sum - k];hash[sum]++;}return count;}
http://www.xdnf.cn/news/958573.html

相关文章:

  • 免费好用的专业提词器有哪些~~~
  • 复盘与导出工具最新版V24.5版本更新--精选新增盘中板块涨停数量
  • 2025季度云服务器排行榜
  • 通过meta分析确定先验并进行贝叶斯分析的构想
  • 常见算法与数据结构
  • std::ratio 简单使用举例
  • 【生产就曲篇】让应用可观测:Actuator监控端点与日志最佳实践
  • 操作系统 | Linux:第一章 初识Linux
  • 使用Docker部署操作系统
  • .NET 2025年第 75 期工具库和资源汇总
  • 【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法
  • StarRocks 全面向量化执行引擎深度解析
  • Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
  • YoloV8改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用
  • 【三方库研读】facebook/folly中File类原理与作用深度解析
  • PydanticAI快速入门示例
  • JS手写代码篇----使用Promise封装AJAX请求
  • 内网im,局域网环境下BeeWorks 如何保障数据安全?
  • MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
  • 基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
  • GraphRAG优化新思路-开源的ROGRAG框架
  • python训练营打卡第49天
  • 三元组 题解
  • 日志的具体使用
  • deepseek+coze开发的智能体页面
  • 链表的实现与介绍
  • codeforces C. Cool Partition
  • X86架构离线环境安装Ollama
  • DPC密度峰值聚类
  • 【MPC-C++】qpOASES 源码编译与链接,编译器设置细节