优选算法——前缀和(5):和为 K 的子数组

优选算法——前缀和(5):和为 K 的子数组
示例图

🔥近津薪荼: [个人主页]🎬个人专栏: 《近津薪荼的算法日迹》《Linux操作系统及网络基础知识分享》《c++基础知识详解》《c语言基础知识详解》✨不要物化,矮化,弱化,钝化自己,保持锋芒,不要停止学习这个世界上只有两个人真正在注意着你八岁的你,和八十岁的你,他们此刻正在注视着你,一个希望你 勇敢开始,一个希望你 不留遗憾


1.上期参考代码

classSolution{public: vector<int>productExceptSelf(vector<int>& nums){int n=nums.size(); vector<int>front(n,1);for(int i=1;i<n;i++){ front[i]=front[i-1]*nums[i-1];} vector<int>back(n,1);for(int i=n-2;i>=0;i--){ back[i]=back[i+1]*nums[i+1];} vector<int>ret(n);for(int i=0;i<n;i++){ ret[i]=front[i]*back[i];}return ret;}};

2.本期知识点导图

3.本期要讲解的题目是

和为 K 的子数组

要点:

  • 子数组是数组元素的连续非空排列
  • 注意数组元素有正有负

4.解题

4.1 暴力解法:

暴力枚举,算出所有子数组的和,需嵌套3层循环,时间复杂度O(N3)(前两层枚举子数组左右区间,里层数组求和)

4.2优解

思考

联系我们之前做过双指针,滑动窗口的题,寻找符合条件的子数组,我们这道题目可以使用吗?

使用双指针解决问题是利用双指针的不回退降低遍历数组的时间复杂度 ,其要依赖窗口信息的单调性来实现

本题数组元素包含0和负数,导致求和(窗口信息)不具有单调性了!

我们思考能否由我们自己塑造单调性呢,显然做不到,目前我们塑造单调性,只使用过排序,然而排序并不能解决求和的单调性问题

双指针的思路只能放弃

对于数组求和,我们还接接触过一种算法:前缀和

前缀和

用前缀和,就别管那么多了,直接在数组前n项和的变式上,摸索摸索

如图:我们将数组抽象成一个线条方便画图

画完发现像个嘴唇

上图中,是对于数组中随机的一个符合条件的子数组进行的分析

图中子数组的右区间是 i

我们发现子数组和为k,那么它前边的区间部分的和,必然是sum[ i ]-k

核心思想

那么我们就可以推出,对于数组的前i项,其前缀和数组中存在值为sum[ i ]-k的话,必然存在一个子数组,它的和为k

我们要统计和为k的子数组的个数,即统计i之前的数组的前缀和为sum[i]-k的个数,使用hash表即可,统计完之后,把它累加给ret即可

细节
  • 不可以也没必要一次性把所有的前缀和全部算出来,因为在i之后,有新的元素的加入,可能还会有满足前缀和为sum[i]-k的位置出现,比如i+1的位置为-1,i+2的位置为1。sum[i+2]-k等于sum[i]-k,但是它的位置就不对了,没有对应的和为k的子数组,但是我们统计的标准是统计前缀和为sum[i]-k,hash会把它统计到,属于无效统计。
  • 在前i-1个位置的前缀和中汇总数组的前缀和为sum[i]-k的个数,然后再把sum[i]加入到哈希表中,这是为了防止k=0时的误判,若k=0,先将sum[i]加入到哈希表,不管是否有和为0的子数组,sum[i]必然满足与sum[i]-k相等的条件,这样我们的判断标准就失灵了。
  • 如果sum[i]本身就为k,那么sum[i]-k等于0,那么sum[i]也是满足条件的,但是我们hash只统计前i-1个位置,所以在开始之前,hash[0]的值就应该是1。

代码逻辑:

  • 初始化hash[0]=1,ret

— 进入循环,遍历数组

  • 求i位置的前缀和
  • 汇总符合条件的数组个数
  • 将i位置的前缀和统计到hash

5.下期要讲解的题目是:

和可被 K 整除的子数组

6.嗟食

如果小编写的内容对佬有帮助,还请大佬点点三连加关注哦

在这里插入图片描述


佬的支持就是我前进的最大动力~

期待与佬的再次相遇~

Read more

【C++:异常】C++ 异常处理完全指南:从理论到实践,深入理解栈展开与最佳实践

【C++:异常】C++ 异常处理完全指南:从理论到实践,深入理解栈展开与最佳实践

🎬 个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬 艾莉丝的简介: 🎬 艾莉丝的C++专栏简介: 文章目录 * C++学习阶段的三个参考文档 * 1 ~> 异常的概念 * 2 ~> 异常的使用层 * 2.1 异常的抛出和捕获 * 2.2 栈展开 * 2.2.1 理论 * 2.2.2 最佳实践 * 2.3 查找匹配的处理代码 * 2.3.

By Ne0inhk
C++进阶:(十六)从裸指针到智能指针,C++ 内存管理的 “自动驾驶” 进化之路

C++进阶:(十六)从裸指针到智能指针,C++ 内存管理的 “自动驾驶” 进化之路

目录 前言 一、裸指针的 “血泪史”:为什么我们需要智能指针? 1.1 内存泄漏:最常见的 “噩梦” 1.2 二次释放:致命的 “双重打击” 1.3 野指针:潜伏的 “幽灵” 1.4 异常安全:被忽略的 “隐形杀手” 1.5 智能指针的核心使命 二、智能指针的 “三驾马车”:unique_ptr、shared_ptr、weak_ptr 2.1 unique_ptr:独占所有权的 “独行侠” 2.1.1 unique_ptr 的核心原理

By Ne0inhk
C++ 函数指针与回调函数深度解析

C++ 函数指针与回调函数深度解析

第32篇:C++ 函数指针与回调函数深度解析 一、学习目标与重点 * 掌握函数指针的定义、声明、初始化及调用方式 * 理解函数指针的核心应用场景,能够灵活运用函数指针优化代码 * 掌握回调函数的概念、实现原理及注册机制 * 能够独立编写回调函数案例,解决实际开发中的解耦需求 * 理解函数指针与typedef、std::function的结合使用技巧 * 规避函数指针使用中的常见错误(类型不匹配、空指针调用等) 💡 核心重点:函数指针的类型匹配规则、回调函数的注册与执行流程、函数指针与现代C++特性的结合 二、函数指针基础认知 2.1 什么是函数指针 函数指针是指向函数的指针变量,本质是指针,但它存储的不是普通数据的地址,而是函数在内存中的入口地址。通过函数指针,我们可以间接调用函数,实现“以指针方式操作函数”的灵活编程模式。 🗄️ 类比理解: * 普通指针:int* p 指向int类型数据,通过*p访问数据 * 函数指针:int (*p)(int,

By Ne0inhk
C++ 入门全指南:从发展史到第一个程序,命名空间 + 输入输出手把手讲

C++ 入门全指南:从发展史到第一个程序,命名空间 + 输入输出手把手讲

目录 一、C++的发展历史 1.发展历史 2.C++的版本更新 3.C++的参考文档 二、C++的学习建议 1.C++的应用领域: 2.学习书籍推荐: 三、C++的第一个程序 四、命名空间 1.namespace的价值: 2.namespace的定义: 1)使用namespace来命名空间,以及使用命名空间(详解见注释): 2)命名空间的嵌套使用 3)多文件定义的命名空间问题 3.namespace命名空间的使用: 1)指定命名空间访问 2)using将命名空间中某个成员展开 3)展开命名空间中全部成员 五、C++输入&输出

By Ne0inhk